diff options
Diffstat (limited to 'Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions')
50 files changed, 23042 insertions, 0 deletions
diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal.c new file mode 100755 index 0000000..7ba683f --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal.c @@ -0,0 +1,242 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_bitreversal.c + * Description: Bitreversal functions + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + +void arm_bitreversal_f32( + float32_t * pSrc, + uint16_t fftSize, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + +/** + @brief In-place floating-point bit reversal function. + @param[in,out] pSrc points to in-place floating-point data buffer + @param[in] fftSize length of FFT + @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table + @param[in] pBitRevTab points to bit reversal table + */ + +ARM_DSP_ATTRIBUTE void arm_bitreversal_f32( + float32_t * pSrc, + uint16_t fftSize, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab) +{ + uint16_t fftLenBy2, fftLenBy2p1; + uint16_t i, j; + float32_t in; + + /* Initializations */ + j = 0U; + fftLenBy2 = fftSize >> 1U; + fftLenBy2p1 = (fftSize >> 1U) + 1U; + + /* Bit Reversal Implementation */ + for (i = 0U; i <= (fftLenBy2 - 2U); i += 2U) + { + if (i < j) + { + /* pSrc[i] <-> pSrc[j]; */ + in = pSrc[2U * i]; + pSrc[2U * i] = pSrc[2U * j]; + pSrc[2U * j] = in; + + /* pSrc[i+1U] <-> pSrc[j+1U] */ + in = pSrc[(2U * i) + 1U]; + pSrc[(2U * i) + 1U] = pSrc[(2U * j) + 1U]; + pSrc[(2U * j) + 1U] = in; + + /* pSrc[i+fftLenBy2p1] <-> pSrc[j+fftLenBy2p1] */ + in = pSrc[2U * (i + fftLenBy2p1)]; + pSrc[2U * (i + fftLenBy2p1)] = pSrc[2U * (j + fftLenBy2p1)]; + pSrc[2U * (j + fftLenBy2p1)] = in; + + /* pSrc[i+fftLenBy2p1+1U] <-> pSrc[j+fftLenBy2p1+1U] */ + in = pSrc[(2U * (i + fftLenBy2p1)) + 1U]; + pSrc[(2U * (i + fftLenBy2p1)) + 1U] = + pSrc[(2U * (j + fftLenBy2p1)) + 1U]; + pSrc[(2U * (j + fftLenBy2p1)) + 1U] = in; + + } + + /* pSrc[i+1U] <-> pSrc[j+1U] */ + in = pSrc[2U * (i + 1U)]; + pSrc[2U * (i + 1U)] = pSrc[2U * (j + fftLenBy2)]; + pSrc[2U * (j + fftLenBy2)] = in; + + /* pSrc[i+2U] <-> pSrc[j+2U] */ + in = pSrc[(2U * (i + 1U)) + 1U]; + pSrc[(2U * (i + 1U)) + 1U] = pSrc[(2U * (j + fftLenBy2)) + 1U]; + pSrc[(2U * (j + fftLenBy2)) + 1U] = in; + + /* Reading the index for the bit reversal */ + j = *pBitRevTab; + + /* Updating the bit reversal index depending on the fft length */ + pBitRevTab += bitRevFactor; + } +} + +void arm_bitreversal_q31( + q31_t * pSrc, + uint32_t fftLen, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + +/** + @brief In-place Q31 bit reversal function. + @param[in,out] pSrc points to in-place Q31 data buffer. + @param[in] fftLen length of FFT. + @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table + @param[in] pBitRevTab points to bit reversal table +*/ + +ARM_DSP_ATTRIBUTE void arm_bitreversal_q31( + q31_t * pSrc, + uint32_t fftLen, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab) +{ + uint32_t fftLenBy2, fftLenBy2p1, i, j; + q31_t in; + + /* Initializations */ + j = 0U; + fftLenBy2 = fftLen / 2U; + fftLenBy2p1 = (fftLen / 2U) + 1U; + + /* Bit Reversal Implementation */ + for (i = 0U; i <= (fftLenBy2 - 2U); i += 2U) + { + if (i < j) + { + /* pSrc[i] <-> pSrc[j]; */ + in = pSrc[2U * i]; + pSrc[2U * i] = pSrc[2U * j]; + pSrc[2U * j] = in; + + /* pSrc[i+1U] <-> pSrc[j+1U] */ + in = pSrc[(2U * i) + 1U]; + pSrc[(2U * i) + 1U] = pSrc[(2U * j) + 1U]; + pSrc[(2U * j) + 1U] = in; + + /* pSrc[i+fftLenBy2p1] <-> pSrc[j+fftLenBy2p1] */ + in = pSrc[2U * (i + fftLenBy2p1)]; + pSrc[2U * (i + fftLenBy2p1)] = pSrc[2U * (j + fftLenBy2p1)]; + pSrc[2U * (j + fftLenBy2p1)] = in; + + /* pSrc[i+fftLenBy2p1+1U] <-> pSrc[j+fftLenBy2p1+1U] */ + in = pSrc[(2U * (i + fftLenBy2p1)) + 1U]; + pSrc[(2U * (i + fftLenBy2p1)) + 1U] = + pSrc[(2U * (j + fftLenBy2p1)) + 1U]; + pSrc[(2U * (j + fftLenBy2p1)) + 1U] = in; + + } + + /* pSrc[i+1U] <-> pSrc[j+1U] */ + in = pSrc[2U * (i + 1U)]; + pSrc[2U * (i + 1U)] = pSrc[2U * (j + fftLenBy2)]; + pSrc[2U * (j + fftLenBy2)] = in; + + /* pSrc[i+2U] <-> pSrc[j+2U] */ + in = pSrc[(2U * (i + 1U)) + 1U]; + pSrc[(2U * (i + 1U)) + 1U] = pSrc[(2U * (j + fftLenBy2)) + 1U]; + pSrc[(2U * (j + fftLenBy2)) + 1U] = in; + + /* Reading the index for the bit reversal */ + j = *pBitRevTab; + + /* Updating the bit reversal index depending on the fft length */ + pBitRevTab += bitRevFactor; + } +} + +void arm_bitreversal_q15( + q15_t * pSrc16, + uint32_t fftLen, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + + +/** + @brief In-place Q15 bit reversal function. + @param[in,out] pSrc16 points to in-place Q15 data buffer + @param[in] fftLen length of FFT + @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table + @param[in] pBitRevTab points to bit reversal table +*/ + +ARM_DSP_ATTRIBUTE void arm_bitreversal_q15( + q15_t * pSrc16, + uint32_t fftLen, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab) +{ + q31_t *pSrc = (q31_t *) pSrc16; + q31_t in; + uint32_t fftLenBy2, fftLenBy2p1; + uint32_t i, j; + + /* Initializations */ + j = 0U; + fftLenBy2 = fftLen / 2U; + fftLenBy2p1 = (fftLen / 2U) + 1U; + + /* Bit Reversal Implementation */ + for (i = 0U; i <= (fftLenBy2 - 2U); i += 2U) + { + if (i < j) + { + /* pSrc[i] <-> pSrc[j]; */ + /* pSrc[i+1U] <-> pSrc[j+1U] */ + in = pSrc[i]; + pSrc[i] = pSrc[j]; + pSrc[j] = in; + + /* pSrc[i + fftLenBy2p1] <-> pSrc[j + fftLenBy2p1]; */ + /* pSrc[i + fftLenBy2p1+1U] <-> pSrc[j + fftLenBy2p1+1U] */ + in = pSrc[i + fftLenBy2p1]; + pSrc[i + fftLenBy2p1] = pSrc[j + fftLenBy2p1]; + pSrc[j + fftLenBy2p1] = in; + } + + /* pSrc[i+1U] <-> pSrc[j+fftLenBy2]; */ + /* pSrc[i+2] <-> pSrc[j+fftLenBy2+1U] */ + in = pSrc[i + 1U]; + pSrc[i + 1U] = pSrc[j + fftLenBy2]; + pSrc[j + fftLenBy2] = in; + + /* Reading the index for the bit reversal */ + j = *pBitRevTab; + + /* Updating the bit reversal index depending on the fft length */ + pBitRevTab += bitRevFactor; + } +} diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal2.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal2.c new file mode 100755 index 0000000..fe63e97 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal2.c @@ -0,0 +1,148 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_bitreversal2.c + * Description: Bitreversal functions + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ +/* + * Copyright (C) 2019 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + +void arm_bitreversal_64( + uint64_t *pSrc, + const uint16_t bitRevLen, + const uint16_t *pBitRevTab); + + +/** + @brief In-place 64 bit reversal function. + @param[in,out] pSrc points to in-place buffer of unknown 64-bit data type + @param[in] bitRevLen bit reversal table length + @param[in] pBitRevTab points to bit reversal table +*/ + +ARM_DSP_ATTRIBUTE void arm_bitreversal_64( + uint64_t *pSrc, + const uint16_t bitRevLen, + const uint16_t *pBitRevTab) +{ + uint64_t a, b, tmp; + uint32_t i; + + for (i = 0; i < bitRevLen; ) + { + a = pBitRevTab[i ] >> 2; + b = pBitRevTab[i + 1] >> 2; + + //real + tmp = pSrc[a]; + pSrc[a] = pSrc[b]; + pSrc[b] = tmp; + + //complex + tmp = pSrc[a+1]; + pSrc[a+1] = pSrc[b+1]; + pSrc[b+1] = tmp; + + i += 2; + } +} + +void arm_bitreversal_32( + uint32_t *pSrc, + const uint16_t bitRevLen, + const uint16_t *pBitRevTab); + +/** + @brief In-place 32 bit reversal function. + @param[in,out] pSrc points to in-place buffer of unknown 32-bit data type + @param[in] bitRevLen bit reversal table length + @param[in] pBitRevTab points to bit reversal table +*/ + +ARM_DSP_ATTRIBUTE void arm_bitreversal_32( + uint32_t *pSrc, + const uint16_t bitRevLen, + const uint16_t *pBitRevTab) +{ + uint32_t a, b, i, tmp; + + for (i = 0; i < bitRevLen; ) + { + a = pBitRevTab[i ] >> 2; + b = pBitRevTab[i + 1] >> 2; + + //real + tmp = pSrc[a]; + pSrc[a] = pSrc[b]; + pSrc[b] = tmp; + + //complex + tmp = pSrc[a+1]; + pSrc[a+1] = pSrc[b+1]; + pSrc[b+1] = tmp; + + i += 2; + } +} + +void arm_bitreversal_16( + uint16_t *pSrc, + const uint16_t bitRevLen, + const uint16_t *pBitRevTab); + + +/** + @brief In-place 16 bit reversal function. + @param[in,out] pSrc points to in-place buffer of unknown 16-bit data type + @param[in] bitRevLen bit reversal table length + @param[in] pBitRevTab points to bit reversal table +*/ + +ARM_DSP_ATTRIBUTE void arm_bitreversal_16( + uint16_t *pSrc, + const uint16_t bitRevLen, + const uint16_t *pBitRevTab) +{ + uint16_t a, b, tmp; + uint32_t i; + + for (i = 0; i < bitRevLen; ) + { + a = pBitRevTab[i ] >> 2; + b = pBitRevTab[i + 1] >> 2; + + //real + tmp = pSrc[a]; + pSrc[a] = pSrc[b]; + pSrc[b] = tmp; + + //complex + tmp = pSrc[a+1]; + pSrc[a+1] = pSrc[b+1]; + pSrc[b+1] = tmp; + + i += 2; + } +} diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal_f16.c new file mode 100755 index 0000000..80c5880 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_bitreversal_f16.c @@ -0,0 +1,112 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_bitreversal_f16.c + * Description: Bitreversal functions + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" + + + +/* +* @brief In-place bit reversal function. +* @param[in, out] *pSrc points to the in-place buffer of floating-point data type. +* @param[in] fftSize length of the FFT. +* @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table. +* @param[in] *pBitRevTab points to the bit reversal table. +*/ + +#if defined(ARM_FLOAT16_SUPPORTED) + +void arm_bitreversal_f16( +float16_t * pSrc, +uint16_t fftSize, +uint16_t bitRevFactor, +const uint16_t * pBitRevTab); + +ARM_DSP_ATTRIBUTE void arm_bitreversal_f16( +float16_t * pSrc, +uint16_t fftSize, +uint16_t bitRevFactor, +const uint16_t * pBitRevTab) +{ + uint16_t fftLenBy2, fftLenBy2p1; + uint16_t i, j; + float16_t in; + + /* Initializations */ + j = 0U; + fftLenBy2 = fftSize >> 1U; + fftLenBy2p1 = (fftSize >> 1U) + 1U; + + /* Bit Reversal Implementation */ + for (i = 0U; i <= (fftLenBy2 - 2U); i += 2U) + { + if (i < j) + { + /* pSrc[i] <-> pSrc[j]; */ + in = pSrc[2U * i]; + pSrc[2U * i] = pSrc[2U * j]; + pSrc[2U * j] = in; + + /* pSrc[i+1U] <-> pSrc[j+1U] */ + in = pSrc[(2U * i) + 1U]; + pSrc[(2U * i) + 1U] = pSrc[(2U * j) + 1U]; + pSrc[(2U * j) + 1U] = in; + + /* pSrc[i+fftLenBy2p1] <-> pSrc[j+fftLenBy2p1] */ + in = pSrc[2U * (i + fftLenBy2p1)]; + pSrc[2U * (i + fftLenBy2p1)] = pSrc[2U * (j + fftLenBy2p1)]; + pSrc[2U * (j + fftLenBy2p1)] = in; + + /* pSrc[i+fftLenBy2p1+1U] <-> pSrc[j+fftLenBy2p1+1U] */ + in = pSrc[(2U * (i + fftLenBy2p1)) + 1U]; + pSrc[(2U * (i + fftLenBy2p1)) + 1U] = + pSrc[(2U * (j + fftLenBy2p1)) + 1U]; + pSrc[(2U * (j + fftLenBy2p1)) + 1U] = in; + + } + + /* pSrc[i+1U] <-> pSrc[j+1U] */ + in = pSrc[2U * (i + 1U)]; + pSrc[2U * (i + 1U)] = pSrc[2U * (j + fftLenBy2)]; + pSrc[2U * (j + fftLenBy2)] = in; + + /* pSrc[i+2U] <-> pSrc[j+2U] */ + in = pSrc[(2U * (i + 1U)) + 1U]; + pSrc[(2U * (i + 1U)) + 1U] = pSrc[(2U * (j + fftLenBy2)) + 1U]; + pSrc[(2U * (j + fftLenBy2)) + 1U] = in; + + /* Reading the index for the bit reversal */ + j = *pBitRevTab; + + /* Updating the bit reversal index depending on the fft length */ + pBitRevTab += bitRevFactor; + } +} +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f16.c new file mode 100755 index 0000000..2ddcff8 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f16.c @@ -0,0 +1,753 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_f32.c + * Description: Combined Radix Decimation in Frequency CFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" +#include "arm_common_tables_f16.h" + + +#if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_helium_utils.h" +#include "arm_vec_fft.h" +#include "arm_mve_tables_f16.h" + + +static float16_t arm_inverse_fft_length_f16(uint16_t fftLen) +{ + float16_t retValue=1.0; + + switch (fftLen) + { + + case 4096U: + retValue = (float16_t)0.000244140625f; + break; + + case 2048U: + retValue = (float16_t)0.00048828125f; + break; + + case 1024U: + retValue = (float16_t)0.0009765625f; + break; + + case 512U: + retValue = (float16_t)0.001953125f; + break; + + case 256U: + retValue = (float16_t)0.00390625f; + break; + + case 128U: + retValue = (float16_t)0.0078125f; + break; + + case 64U: + retValue = (float16_t)0.015625f; + break; + + case 32U: + retValue = (float16_t)0.03125f; + break; + + case 16U: + retValue = (float16_t)0.0625f; + break; + + + default: + break; + } + return(retValue); +} + + +static void _arm_radix4_butterfly_f16_mve(const arm_cfft_instance_f16 * S,float16_t * pSrc, uint32_t fftLen) +{ + f16x8_t vecTmp0, vecTmp1; + f16x8_t vecSum0, vecDiff0, vecSum1, vecDiff1; + f16x8_t vecA, vecB, vecC, vecD; + uint32_t blkCnt; + uint32_t n1, n2; + uint32_t stage = 0; + int32_t iter = 1; + static const int32_t strides[4] = + { ( 0 - 16) * (int32_t)sizeof(float16_t *) + , ( 4 - 16) * (int32_t)sizeof(float16_t *) + , ( 8 - 16) * (int32_t)sizeof(float16_t *) + , (12 - 16) * (int32_t)sizeof(float16_t *)}; + + n2 = fftLen; + n1 = n2; + n2 >>= 2u; + for (int k = fftLen / 4u; k > 1; k >>= 2) + { + float16_t const *p_rearranged_twiddle_tab_stride1 = + &S->rearranged_twiddle_stride1[ + S->rearranged_twiddle_tab_stride1_arr[stage]]; + float16_t const *p_rearranged_twiddle_tab_stride2 = + &S->rearranged_twiddle_stride2[ + S->rearranged_twiddle_tab_stride2_arr[stage]]; + float16_t const *p_rearranged_twiddle_tab_stride3 = + &S->rearranged_twiddle_stride3[ + S->rearranged_twiddle_tab_stride3_arr[stage]]; + float16_t * pBase = pSrc; + for (int i = 0; i < iter; i++) + { + float16_t *inA = pBase; + float16_t *inB = inA + n2 * CMPLX_DIM; + float16_t *inC = inB + n2 * CMPLX_DIM; + float16_t *inD = inC + n2 * CMPLX_DIM; + float16_t const *pW1 = p_rearranged_twiddle_tab_stride1; + float16_t const *pW2 = p_rearranged_twiddle_tab_stride2; + float16_t const *pW3 = p_rearranged_twiddle_tab_stride3; + f16x8_t vecW; + + blkCnt = n2 / 4; + /* + * load 2 f16 complex pair + */ + vecA = vldrhq_f16(inA); + vecC = vldrhq_f16(inC); + while (blkCnt > 0U) + { + vecB = vldrhq_f16(inB); + vecD = vldrhq_f16(inD); + + vecSum0 = vecA + vecC; /* vecSum0 = vaddq(vecA, vecC) */ + vecDiff0 = vecA - vecC; /* vecSum0 = vsubq(vecA, vecC) */ + + vecSum1 = vecB + vecD; + vecDiff1 = vecB - vecD; + /* + * [ 1 1 1 1 ] * [ A B C D ]' .* 1 + */ + vecTmp0 = vecSum0 + vecSum1; + vst1q(inA, vecTmp0); + inA += 8; + + /* + * [ 1 -1 1 -1 ] * [ A B C D ]' + */ + vecTmp0 = vecSum0 - vecSum1; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]'.* W2 + */ + vecW = vld1q(pW2); + pW2 += 8; + vecTmp1 = MVE_CMPLX_MULT_FLT_Conj_AxB(vecW, vecTmp0); + vst1q(inB, vecTmp1); + inB += 8; + + /* + * [ 1 -i -1 +i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_SUB_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 -i -1 +i ] * [ A B C D ]'.* W1 + */ + vecW = vld1q(pW1); + pW1 +=8; + vecTmp1 = MVE_CMPLX_MULT_FLT_Conj_AxB(vecW, vecTmp0); + vst1q(inC, vecTmp1); + inC += 8; + + /* + * [ 1 +i -1 -i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_ADD_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 +i -1 -i ] * [ A B C D ]'.* W3 + */ + vecW = vld1q(pW3); + pW3 += 8; + vecTmp1 = MVE_CMPLX_MULT_FLT_Conj_AxB(vecW, vecTmp0); + vst1q(inD, vecTmp1); + inD += 8; + + vecA = vldrhq_f16(inA); + vecC = vldrhq_f16(inC); + + blkCnt--; + } + pBase += CMPLX_DIM * n1; + } + n1 = n2; + n2 >>= 2u; + iter = iter << 2; + stage++; + } + + /* + * start of Last stage process + */ + uint32x4_t vecScGathAddr = vld1q_u32((uint32_t*)strides); + vecScGathAddr = vecScGathAddr + (uint32_t) pSrc; + + /* load scheduling */ + vecA = (f16x8_t)vldrwq_gather_base_wb_f32(&vecScGathAddr, 64); + vecC = (f16x8_t)vldrwq_gather_base_f32(vecScGathAddr, 8); + + blkCnt = (fftLen >> 4); + while (blkCnt > 0U) + { + vecSum0 = vecA + vecC; /* vecSum0 = vaddq(vecA, vecC) */ + vecDiff0 = vecA - vecC; /* vecSum0 = vsubq(vecA, vecC) */ + + vecB = (f16x8_t)vldrwq_gather_base_f32(vecScGathAddr, 4); + vecD = (f16x8_t)vldrwq_gather_base_f32(vecScGathAddr, 12); + + vecSum1 = vecB + vecD; + vecDiff1 = vecB - vecD; + + /* pre-load for next iteration */ + vecA = (f16x8_t)vldrwq_gather_base_wb_f32(&vecScGathAddr, 64); + vecC = (f16x8_t)vldrwq_gather_base_f32(vecScGathAddr, 8); + + vecTmp0 = vecSum0 + vecSum1; + vstrwq_scatter_base_f32(vecScGathAddr, -64, (f32x4_t)vecTmp0); + + vecTmp0 = vecSum0 - vecSum1; + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 4, (f32x4_t)vecTmp0); + + vecTmp0 = MVE_CMPLX_SUB_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 8, (f32x4_t)vecTmp0); + + vecTmp0 = MVE_CMPLX_ADD_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 12, (f32x4_t)vecTmp0); + + blkCnt--; + } + + /* + * End of last stage process + */ +} + +static void arm_cfft_radix4by2_f16_mve(const arm_cfft_instance_f16 * S, float16_t *pSrc, uint32_t fftLen) +{ + float16_t const *pCoefVec; + float16_t const *pCoef = S->pTwiddle; + float16_t *pIn0, *pIn1; + uint32_t n2; + uint32_t blkCnt; + f16x8_t vecIn0, vecIn1, vecSum, vecDiff; + f16x8_t vecCmplxTmp, vecTw; + + + n2 = fftLen >> 1; + pIn0 = pSrc; + pIn1 = pSrc + fftLen; + pCoefVec = pCoef; + + blkCnt = n2 / 4; + while (blkCnt > 0U) + { + vecIn0 = *(f16x8_t *) pIn0; + vecIn1 = *(f16x8_t *) pIn1; + vecTw = vld1q(pCoefVec); + pCoefVec += 8; + + vecSum = vaddq(vecIn0, vecIn1); + vecDiff = vsubq(vecIn0, vecIn1); + + vecCmplxTmp = MVE_CMPLX_MULT_FLT_Conj_AxB(vecTw, vecDiff); + + vst1q(pIn0, vecSum); + pIn0 += 8; + vst1q(pIn1, vecCmplxTmp); + pIn1 += 8; + + blkCnt--; + } + + _arm_radix4_butterfly_f16_mve(S, pSrc, n2); + + _arm_radix4_butterfly_f16_mve(S, pSrc + fftLen, n2); + + pIn0 = pSrc; +} + +static void _arm_radix4_butterfly_inverse_f16_mve(const arm_cfft_instance_f16 * S,float16_t * pSrc, uint32_t fftLen, float16_t onebyfftLen) +{ + f16x8_t vecTmp0, vecTmp1; + f16x8_t vecSum0, vecDiff0, vecSum1, vecDiff1; + f16x8_t vecA, vecB, vecC, vecD; + uint32_t blkCnt; + uint32_t n1, n2; + uint32_t stage = 0; + int32_t iter = 1; + static const int32_t strides[4] = { + ( 0 - 16) * (int32_t)sizeof(q31_t *), + ( 4 - 16) * (int32_t)sizeof(q31_t *), + ( 8 - 16) * (int32_t)sizeof(q31_t *), + (12 - 16) * (int32_t)sizeof(q31_t *) + }; + + n2 = fftLen; + n1 = n2; + n2 >>= 2u; + for (int k = fftLen / 4; k > 1; k >>= 2) + { + float16_t const *p_rearranged_twiddle_tab_stride1 = + &S->rearranged_twiddle_stride1[ + S->rearranged_twiddle_tab_stride1_arr[stage]]; + float16_t const *p_rearranged_twiddle_tab_stride2 = + &S->rearranged_twiddle_stride2[ + S->rearranged_twiddle_tab_stride2_arr[stage]]; + float16_t const *p_rearranged_twiddle_tab_stride3 = + &S->rearranged_twiddle_stride3[ + S->rearranged_twiddle_tab_stride3_arr[stage]]; + + float16_t * pBase = pSrc; + for (int i = 0; i < iter; i++) + { + float16_t *inA = pBase; + float16_t *inB = inA + n2 * CMPLX_DIM; + float16_t *inC = inB + n2 * CMPLX_DIM; + float16_t *inD = inC + n2 * CMPLX_DIM; + float16_t const *pW1 = p_rearranged_twiddle_tab_stride1; + float16_t const *pW2 = p_rearranged_twiddle_tab_stride2; + float16_t const *pW3 = p_rearranged_twiddle_tab_stride3; + f16x8_t vecW; + + blkCnt = n2 / 4; + /* + * load 2 f32 complex pair + */ + vecA = vldrhq_f16(inA); + vecC = vldrhq_f16(inC); + while (blkCnt > 0U) + { + vecB = vldrhq_f16(inB); + vecD = vldrhq_f16(inD); + + vecSum0 = vecA + vecC; /* vecSum0 = vaddq(vecA, vecC) */ + vecDiff0 = vecA - vecC; /* vecSum0 = vsubq(vecA, vecC) */ + + vecSum1 = vecB + vecD; + vecDiff1 = vecB - vecD; + /* + * [ 1 1 1 1 ] * [ A B C D ]' .* 1 + */ + vecTmp0 = vecSum0 + vecSum1; + vst1q(inA, vecTmp0); + inA += 8; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]' + */ + vecTmp0 = vecSum0 - vecSum1; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]'.* W1 + */ + vecW = vld1q(pW2); + pW2 += 8; + vecTmp1 = MVE_CMPLX_MULT_FLT_AxB(vecW, vecTmp0); + vst1q(inB, vecTmp1); + inB += 8; + + /* + * [ 1 -i -1 +i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_ADD_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 -i -1 +i ] * [ A B C D ]'.* W2 + */ + vecW = vld1q(pW1); + pW1 += 8; + vecTmp1 = MVE_CMPLX_MULT_FLT_AxB(vecW, vecTmp0); + vst1q(inC, vecTmp1); + inC += 8; + + /* + * [ 1 +i -1 -i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_SUB_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 +i -1 -i ] * [ A B C D ]'.* W3 + */ + vecW = vld1q(pW3); + pW3 += 8; + vecTmp1 = MVE_CMPLX_MULT_FLT_AxB(vecW, vecTmp0); + vst1q(inD, vecTmp1); + inD += 8; + + vecA = vldrhq_f16(inA); + vecC = vldrhq_f16(inC); + + blkCnt--; + } + pBase += CMPLX_DIM * n1; + } + n1 = n2; + n2 >>= 2u; + iter = iter << 2; + stage++; + } + + /* + * start of Last stage process + */ + uint32x4_t vecScGathAddr = vld1q_u32((uint32_t*)strides); + vecScGathAddr = vecScGathAddr + (uint32_t) pSrc; + + /* + * load scheduling + */ + vecA = (f16x8_t)vldrwq_gather_base_wb_f32(&vecScGathAddr, 64); + vecC = (f16x8_t)vldrwq_gather_base_f32(vecScGathAddr, 8); + + blkCnt = (fftLen >> 4); + while (blkCnt > 0U) + { + vecSum0 = vecA + vecC; /* vecSum0 = vaddq(vecA, vecC) */ + vecDiff0 = vecA - vecC; /* vecSum0 = vsubq(vecA, vecC) */ + + vecB = (f16x8_t)vldrwq_gather_base_f32(vecScGathAddr, 4); + vecD = (f16x8_t)vldrwq_gather_base_f32(vecScGathAddr, 12); + + vecSum1 = vecB + vecD; + vecDiff1 = vecB - vecD; + + vecA = (f16x8_t)vldrwq_gather_base_wb_f32(&vecScGathAddr, 64); + vecC = (f16x8_t)vldrwq_gather_base_f32(vecScGathAddr, 8); + + vecTmp0 = vecSum0 + vecSum1; + vecTmp0 = vecTmp0 * onebyfftLen; + vstrwq_scatter_base_f32(vecScGathAddr, -64, (f32x4_t)vecTmp0); + + vecTmp0 = vecSum0 - vecSum1; + vecTmp0 = vecTmp0 * onebyfftLen; + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 4, (f32x4_t)vecTmp0); + + vecTmp0 = MVE_CMPLX_ADD_A_ixB(vecDiff0, vecDiff1); + vecTmp0 = vecTmp0 * onebyfftLen; + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 8, (f32x4_t)vecTmp0); + + vecTmp0 = MVE_CMPLX_SUB_A_ixB(vecDiff0, vecDiff1); + vecTmp0 = vecTmp0 * onebyfftLen; + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 12, (f32x4_t)vecTmp0); + + blkCnt--; + } + + /* + * End of last stage process + */ +} + +static void arm_cfft_radix4by2_inverse_f16_mve(const arm_cfft_instance_f16 * S,float16_t *pSrc, uint32_t fftLen) +{ + float16_t const *pCoefVec; + float16_t const *pCoef = S->pTwiddle; + float16_t *pIn0, *pIn1; + uint32_t n2; + float16_t onebyfftLen = arm_inverse_fft_length_f16(fftLen); + uint32_t blkCnt; + f16x8_t vecIn0, vecIn1, vecSum, vecDiff; + f16x8_t vecCmplxTmp, vecTw; + + + n2 = fftLen >> 1; + pIn0 = pSrc; + pIn1 = pSrc + fftLen; + pCoefVec = pCoef; + + blkCnt = n2 / 4; + while (blkCnt > 0U) + { + vecIn0 = *(f16x8_t *) pIn0; + vecIn1 = *(f16x8_t *) pIn1; + vecTw = vld1q(pCoefVec); + pCoefVec += 8; + + vecSum = vaddq(vecIn0, vecIn1); + vecDiff = vsubq(vecIn0, vecIn1); + + vecCmplxTmp = MVE_CMPLX_MULT_FLT_AxB(vecTw, vecDiff); + + vst1q(pIn0, vecSum); + pIn0 += 8; + vst1q(pIn1, vecCmplxTmp); + pIn1 += 8; + + blkCnt--; + } + + _arm_radix4_butterfly_inverse_f16_mve(S, pSrc, n2, onebyfftLen); + + _arm_radix4_butterfly_inverse_f16_mve(S, pSrc + fftLen, n2, onebyfftLen); +} + + +/** + @addtogroup ComplexFFTF16 + @{ + */ + +/** + @brief Processing function for the floating-point complex FFT. + @param[in] S points to an instance of the floating-point CFFT structure + @param[in,out] p1 points to the complex data buffer. Processing occurs in-place + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + +@par Neon version + The neon version has a different API. + The input and output buffers must be + different. + There is a temporary buffer. + The bit reverse flag is not more + available in Neon version. + + @code + void arm_cfft_f16( + const arm_cfft_instance_f16 * S, + const float16_t * pIn, + float16_t * pOut, + float16_t * pBuffer, + uint8_t ifftFlag); + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + */ + + +ARM_DSP_ATTRIBUTE void arm_cfft_f16( + const arm_cfft_instance_f16 * S, + float16_t * pSrc, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t fftLen = S->fftLen; + + if (ifftFlag == 1U) { + + switch (fftLen) { + case 16: + case 64: + case 256: + case 1024: + case 4096: + _arm_radix4_butterfly_inverse_f16_mve(S, pSrc, fftLen, arm_inverse_fft_length_f16(S->fftLen)); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_inverse_f16_mve(S, pSrc, fftLen); + break; + } + } else { + switch (fftLen) { + case 16: + case 64: + case 256: + case 1024: + case 4096: + _arm_radix4_butterfly_f16_mve(S, pSrc, fftLen); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_f16_mve(S, pSrc, fftLen); + break; + } + } + + + if (bitReverseFlag) + { + + arm_bitreversal_16_inpl_mve((uint16_t*)pSrc, S->bitRevLength, S->pBitRevTable); + + } +} +#elif defined(ARM_MATH_NEON_FLOAT16) && defined(ARM_FLOAT16_SUPPORTED) +#include "CMSIS_NE10_types.h" +#include "CMSIS_NE10_fft.h" + + + +ARM_DSP_ATTRIBUTE void arm_cfft_f16( + const arm_cfft_instance_f16 * S, + const float16_t * pIn, + float16_t * pOut, + float16_t * pBuffer, /* When used, in is not modified */ + uint8_t ifftFlag) +{ + if (S->algorithm_flag == ARM_MIXED_RADIX_FFT) + { + if (ifftFlag) + { + arm_ne10_mixed_radix_generic_butterfly_inverse_float16_neon (S, + (ne10_fft_cpx_float16_t *)pIn, + (ne10_fft_cpx_float16_t *)pOut, + (ne10_fft_cpx_float16_t *)pBuffer); + } + else + { + arm_ne10_mixed_radix_generic_butterfly_float16_neon (S, + (ne10_fft_cpx_float16_t *)pIn, + (ne10_fft_cpx_float16_t *)pOut, + (ne10_fft_cpx_float16_t *)pBuffer); + } + } + else + { + if (ifftFlag == 0) + { + arm_ne10_mixed_radix_fft_forward_float16_neon (S, + (ne10_fft_cpx_float16_t *)pIn, + (ne10_fft_cpx_float16_t *)pOut, + (ne10_fft_cpx_float16_t *)pBuffer); + } + else + { + arm_ne10_mixed_radix_fft_backward_float16_neon (S, + (ne10_fft_cpx_float16_t *)pIn, + (ne10_fft_cpx_float16_t *)pOut, + (ne10_fft_cpx_float16_t *)pBuffer); + } + } +} +#else + +#if defined(ARM_FLOAT16_SUPPORTED) + +extern void arm_bitreversal_16( + uint16_t * pSrc, + const uint16_t bitRevLen, + const uint16_t * pBitRevTable); + + +extern void arm_cfft_radix4by2_f16( + float16_t * pSrc, + uint32_t fftLen, + const float16_t * pCoef); + +extern void arm_radix4_butterfly_f16( + float16_t * pSrc, + uint16_t fftLen, + const float16_t * pCoef, + uint16_t twidCoefModifier); + +/** + @addtogroup ComplexFFTF16 + @{ + */ + +/** + @brief Processing function for the floating-point complex FFT. + @param[in] S points to an instance of the floating-point CFFT structure + @param[in,out] p1 points to the complex data buffer. Processing occurs in-place + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_f16( + const arm_cfft_instance_f16 * S, + float16_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t L = S->fftLen, l; + float16_t invL, * pSrc; + + if (ifftFlag == 1U) + { + /* Conjugate input data */ + pSrc = p1 + 1; + for(l=0; l<L; l++) + { + *pSrc = -(_Float16)*pSrc; + pSrc += 2; + } + } + + switch (L) + { + + case 16: + case 64: + case 256: + case 1024: + case 4096: + arm_radix4_butterfly_f16 (p1, L, (float16_t*)S->pTwiddle, 1U); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_f16 ( p1, L, (float16_t*)S->pTwiddle); + break; + + } + + if ( bitReverseFlag ) + arm_bitreversal_16((uint16_t*)p1, S->bitRevLength,(uint16_t*)S->pBitRevTable); + + if (ifftFlag == 1U) + { + invL = 1.0f16/(_Float16)L; + /* Conjugate and scale output data */ + pSrc = p1; + for(l=0; l<L; l++) + { + *pSrc++ *= (_Float16)invL ; + *pSrc = -(_Float16)(*pSrc) * (_Float16)invL; + pSrc++; + } + } +} +#endif /* if defined(ARM_FLOAT16_SUPPORTED) */ +#endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */ + +/** + @} end of ComplexFFTF16 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f32.c new file mode 100755 index 0000000..8c81d38 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f32.c @@ -0,0 +1,1306 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_f32.c + * Description: Combined Radix Decimation in Frequency CFFT Floating point processing function + * + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2024 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + +//#include <stdio.h> + +#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_helium_utils.h" +#include "arm_vec_fft.h" +#include "arm_mve_tables.h" + + +static float32_t arm_inverse_fft_length_f32(uint16_t fftLen) +{ + float32_t retValue=1.0; + + switch (fftLen) + { + + case 4096U: + retValue = 0.000244140625; + break; + + case 2048U: + retValue = 0.00048828125; + break; + + case 1024U: + retValue = 0.0009765625f; + break; + + case 512U: + retValue = 0.001953125; + break; + + case 256U: + retValue = 0.00390625f; + break; + + case 128U: + retValue = 0.0078125; + break; + + case 64U: + retValue = 0.015625f; + break; + + case 32U: + retValue = 0.03125; + break; + + case 16U: + retValue = 0.0625f; + break; + + + default: + break; + } + return(retValue); +} + + + + +static void _arm_radix4_butterfly_f32_mve(const arm_cfft_instance_f32 * S,float32_t * pSrc, uint32_t fftLen) +{ + f32x4_t vecTmp0, vecTmp1; + f32x4_t vecSum0, vecDiff0, vecSum1, vecDiff1; + f32x4_t vecA, vecB, vecC, vecD; + uint32_t blkCnt; + uint32_t n1, n2; + uint32_t stage = 0; + int32_t iter = 1; + static const int32_t strides[4] = { + (0 - 16) * (int32_t)sizeof(q31_t *), + (1 - 16) * (int32_t)sizeof(q31_t *), + (8 - 16) * (int32_t)sizeof(q31_t *), + (9 - 16) * (int32_t)sizeof(q31_t *) + }; + + n2 = fftLen; + n1 = n2; + n2 >>= 2u; + for (int k = fftLen / 4u; k > 1; k >>= 2) + { + float32_t const *p_rearranged_twiddle_tab_stride1 = + &S->rearranged_twiddle_stride1[ + S->rearranged_twiddle_tab_stride1_arr[stage]]; + float32_t const *p_rearranged_twiddle_tab_stride2 = + &S->rearranged_twiddle_stride2[ + S->rearranged_twiddle_tab_stride2_arr[stage]]; + float32_t const *p_rearranged_twiddle_tab_stride3 = + &S->rearranged_twiddle_stride3[ + S->rearranged_twiddle_tab_stride3_arr[stage]]; + + float32_t * pBase = pSrc; + for (int i = 0; i < iter; i++) + { + float32_t *inA = pBase; + float32_t *inB = inA + n2 * CMPLX_DIM; + float32_t *inC = inB + n2 * CMPLX_DIM; + float32_t *inD = inC + n2 * CMPLX_DIM; + float32_t const *pW1 = p_rearranged_twiddle_tab_stride1; + float32_t const *pW2 = p_rearranged_twiddle_tab_stride2; + float32_t const *pW3 = p_rearranged_twiddle_tab_stride3; + f32x4_t vecW; + + blkCnt = n2 / 2; + /* + * load 2 f32 complex pair + */ + vecA = vldrwq_f32(inA); + vecC = vldrwq_f32(inC); + while (blkCnt > 0U) + { + vecB = vldrwq_f32(inB); + vecD = vldrwq_f32(inD); + + vecSum0 = vecA + vecC; /* vecSum0 = vaddq(vecA, vecC) */ + vecDiff0 = vecA - vecC; /* vecSum0 = vsubq(vecA, vecC) */ + + vecSum1 = vecB + vecD; + vecDiff1 = vecB - vecD; + /* + * [ 1 1 1 1 ] * [ A B C D ]' .* 1 + */ + vecTmp0 = vecSum0 + vecSum1; + vst1q(inA, vecTmp0); + inA += 4; + + /* + * [ 1 -1 1 -1 ] * [ A B C D ]' + */ + vecTmp0 = vecSum0 - vecSum1; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]'.* W2 + */ + vecW = vld1q(pW2); + pW2 += 4; + vecTmp1 = MVE_CMPLX_MULT_FLT_Conj_AxB(vecW, vecTmp0); + vst1q(inB, vecTmp1); + inB += 4; + + /* + * [ 1 -i -1 +i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_SUB_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 -i -1 +i ] * [ A B C D ]'.* W1 + */ + vecW = vld1q(pW1); + pW1 +=4; + vecTmp1 = MVE_CMPLX_MULT_FLT_Conj_AxB(vecW, vecTmp0); + vst1q(inC, vecTmp1); + inC += 4; + + /* + * [ 1 +i -1 -i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_ADD_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 +i -1 -i ] * [ A B C D ]'.* W3 + */ + vecW = vld1q(pW3); + pW3 += 4; + vecTmp1 = MVE_CMPLX_MULT_FLT_Conj_AxB(vecW, vecTmp0); + vst1q(inD, vecTmp1); + inD += 4; + + vecA = vldrwq_f32(inA); + vecC = vldrwq_f32(inC); + + blkCnt--; + } + pBase += CMPLX_DIM * n1; + } + n1 = n2; + n2 >>= 2u; + iter = iter << 2; + stage++; + } + + /* + * start of Last stage process + */ + uint32x4_t vecScGathAddr = vld1q_u32((uint32_t*)strides); + vecScGathAddr = vecScGathAddr + (uint32_t) pSrc; + + /* load scheduling */ + vecA = vldrwq_gather_base_wb_f32(&vecScGathAddr, 64); + vecC = vldrwq_gather_base_f32(vecScGathAddr, 16); + + blkCnt = (fftLen >> 3); + while (blkCnt > 0U) + { + vecSum0 = vecA + vecC; /* vecSum0 = vaddq(vecA, vecC) */ + vecDiff0 = vecA - vecC; /* vecSum0 = vsubq(vecA, vecC) */ + + vecB = vldrwq_gather_base_f32(vecScGathAddr, 8); + vecD = vldrwq_gather_base_f32(vecScGathAddr, 24); + + vecSum1 = vecB + vecD; + vecDiff1 = vecB - vecD; + + /* pre-load for next iteration */ + vecA = vldrwq_gather_base_wb_f32(&vecScGathAddr, 64); + vecC = vldrwq_gather_base_f32(vecScGathAddr, 16); + + vecTmp0 = vecSum0 + vecSum1; + vstrwq_scatter_base_f32(vecScGathAddr, -64, vecTmp0); + + vecTmp0 = vecSum0 - vecSum1; + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 8, vecTmp0); + + vecTmp0 = MVE_CMPLX_SUB_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 16, vecTmp0); + + vecTmp0 = MVE_CMPLX_ADD_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 24, vecTmp0); + + blkCnt--; + } + + /* + * End of last stage process + */ +} + +static void arm_cfft_radix4by2_f32_mve(const arm_cfft_instance_f32 * S, float32_t *pSrc, uint32_t fftLen) +{ + float32_t const *pCoefVec; + float32_t const *pCoef = S->pTwiddle; + float32_t *pIn0, *pIn1; + uint32_t n2; + uint32_t blkCnt; + f32x4_t vecIn0, vecIn1, vecSum, vecDiff; + f32x4_t vecCmplxTmp, vecTw; + + + n2 = fftLen >> 1; + pIn0 = pSrc; + pIn1 = pSrc + fftLen; + pCoefVec = pCoef; + + blkCnt = n2 / 2; + while (blkCnt > 0U) + { + vecIn0 = *(f32x4_t *) pIn0; + vecIn1 = *(f32x4_t *) pIn1; + vecTw = vld1q(pCoefVec); + pCoefVec += 4; + + vecSum = vecIn0 + vecIn1; + vecDiff = vecIn0 - vecIn1; + + vecCmplxTmp = MVE_CMPLX_MULT_FLT_Conj_AxB(vecTw, vecDiff); + + vst1q(pIn0, vecSum); + pIn0 += 4; + vst1q(pIn1, vecCmplxTmp); + pIn1 += 4; + + blkCnt--; + } + + _arm_radix4_butterfly_f32_mve(S, pSrc, n2); + + _arm_radix4_butterfly_f32_mve(S, pSrc + fftLen, n2); + + pIn0 = pSrc; +} + +static void _arm_radix4_butterfly_inverse_f32_mve(const arm_cfft_instance_f32 * S,float32_t * pSrc, uint32_t fftLen, float32_t onebyfftLen) +{ + f32x4_t vecTmp0, vecTmp1; + f32x4_t vecSum0, vecDiff0, vecSum1, vecDiff1; + f32x4_t vecA, vecB, vecC, vecD; + uint32_t blkCnt; + uint32_t n1, n2; + uint32_t stage = 0; + int32_t iter = 1; + static const int32_t strides[4] = { + (0 - 16) * (int32_t)sizeof(q31_t *), + (1 - 16) * (int32_t)sizeof(q31_t *), + (8 - 16) * (int32_t)sizeof(q31_t *), + (9 - 16) * (int32_t)sizeof(q31_t *) + }; + + n2 = fftLen; + n1 = n2; + n2 >>= 2u; + for (int k = fftLen / 4; k > 1; k >>= 2) + { + float32_t const *p_rearranged_twiddle_tab_stride1 = + &S->rearranged_twiddle_stride1[ + S->rearranged_twiddle_tab_stride1_arr[stage]]; + float32_t const *p_rearranged_twiddle_tab_stride2 = + &S->rearranged_twiddle_stride2[ + S->rearranged_twiddle_tab_stride2_arr[stage]]; + float32_t const *p_rearranged_twiddle_tab_stride3 = + &S->rearranged_twiddle_stride3[ + S->rearranged_twiddle_tab_stride3_arr[stage]]; + + float32_t * pBase = pSrc; + for (int i = 0; i < iter; i++) + { + float32_t *inA = pBase; + float32_t *inB = inA + n2 * CMPLX_DIM; + float32_t *inC = inB + n2 * CMPLX_DIM; + float32_t *inD = inC + n2 * CMPLX_DIM; + float32_t const *pW1 = p_rearranged_twiddle_tab_stride1; + float32_t const *pW2 = p_rearranged_twiddle_tab_stride2; + float32_t const *pW3 = p_rearranged_twiddle_tab_stride3; + f32x4_t vecW; + + blkCnt = n2 / 2; + /* + * load 2 f32 complex pair + */ + vecA = vldrwq_f32(inA); + vecC = vldrwq_f32(inC); + while (blkCnt > 0U) + { + vecB = vldrwq_f32(inB); + vecD = vldrwq_f32(inD); + + vecSum0 = vecA + vecC; /* vecSum0 = vaddq(vecA, vecC) */ + vecDiff0 = vecA - vecC; /* vecSum0 = vsubq(vecA, vecC) */ + + vecSum1 = vecB + vecD; + vecDiff1 = vecB - vecD; + /* + * [ 1 1 1 1 ] * [ A B C D ]' .* 1 + */ + vecTmp0 = vecSum0 + vecSum1; + vst1q(inA, vecTmp0); + inA += 4; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]' + */ + vecTmp0 = vecSum0 - vecSum1; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]'.* W1 + */ + vecW = vld1q(pW2); + pW2 += 4; + vecTmp1 = MVE_CMPLX_MULT_FLT_AxB(vecW, vecTmp0); + vst1q(inB, vecTmp1); + inB += 4; + + /* + * [ 1 -i -1 +i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_ADD_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 -i -1 +i ] * [ A B C D ]'.* W2 + */ + vecW = vld1q(pW1); + pW1 += 4; + vecTmp1 = MVE_CMPLX_MULT_FLT_AxB(vecW, vecTmp0); + vst1q(inC, vecTmp1); + inC += 4; + + /* + * [ 1 +i -1 -i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_SUB_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 +i -1 -i ] * [ A B C D ]'.* W3 + */ + vecW = vld1q(pW3); + pW3 += 4; + vecTmp1 = MVE_CMPLX_MULT_FLT_AxB(vecW, vecTmp0); + vst1q(inD, vecTmp1); + inD += 4; + + vecA = vldrwq_f32(inA); + vecC = vldrwq_f32(inC); + + blkCnt--; + } + pBase += CMPLX_DIM * n1; + } + n1 = n2; + n2 >>= 2u; + iter = iter << 2; + stage++; + } + + /* + * start of Last stage process + */ + uint32x4_t vecScGathAddr = vld1q_u32 ((uint32_t*)strides); + vecScGathAddr = vecScGathAddr + (uint32_t) pSrc; + + /* + * load scheduling + */ + vecA = vldrwq_gather_base_wb_f32(&vecScGathAddr, 64); + vecC = vldrwq_gather_base_f32(vecScGathAddr, 16); + + blkCnt = (fftLen >> 3); + while (blkCnt > 0U) + { + vecSum0 = vecA + vecC; /* vecSum0 = vaddq(vecA, vecC) */ + vecDiff0 = vecA - vecC; /* vecSum0 = vsubq(vecA, vecC) */ + + vecB = vldrwq_gather_base_f32(vecScGathAddr, 8); + vecD = vldrwq_gather_base_f32(vecScGathAddr, 24); + + vecSum1 = vecB + vecD; + vecDiff1 = vecB - vecD; + + vecA = vldrwq_gather_base_wb_f32(&vecScGathAddr, 64); + vecC = vldrwq_gather_base_f32(vecScGathAddr, 16); + + vecTmp0 = vecSum0 + vecSum1; + vecTmp0 = vecTmp0 * onebyfftLen; + vstrwq_scatter_base_f32(vecScGathAddr, -64, vecTmp0); + + vecTmp0 = vecSum0 - vecSum1; + vecTmp0 = vecTmp0 * onebyfftLen; + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 8, vecTmp0); + + vecTmp0 = MVE_CMPLX_ADD_A_ixB(vecDiff0, vecDiff1); + vecTmp0 = vecTmp0 * onebyfftLen; + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 16, vecTmp0); + + vecTmp0 = MVE_CMPLX_SUB_A_ixB(vecDiff0, vecDiff1); + vecTmp0 = vecTmp0 * onebyfftLen; + vstrwq_scatter_base_f32(vecScGathAddr, -64 + 24, vecTmp0); + + blkCnt--; + } + + /* + * End of last stage process + */ +} + +static void arm_cfft_radix4by2_inverse_f32_mve(const arm_cfft_instance_f32 * S,float32_t *pSrc, uint32_t fftLen) +{ + float32_t const *pCoefVec; + float32_t const *pCoef = S->pTwiddle; + float32_t *pIn0, *pIn1; + uint32_t n2; + float32_t onebyfftLen = arm_inverse_fft_length_f32(fftLen); + uint32_t blkCnt; + f32x4_t vecIn0, vecIn1, vecSum, vecDiff; + f32x4_t vecCmplxTmp, vecTw; + + + n2 = fftLen >> 1; + pIn0 = pSrc; + pIn1 = pSrc + fftLen; + pCoefVec = pCoef; + + blkCnt = n2 / 2; + while (blkCnt > 0U) + { + vecIn0 = *(f32x4_t *) pIn0; + vecIn1 = *(f32x4_t *) pIn1; + vecTw = vld1q(pCoefVec); + pCoefVec += 4; + + vecSum = vecIn0 + vecIn1; + vecDiff = vecIn0 - vecIn1; + + vecCmplxTmp = MVE_CMPLX_MULT_FLT_AxB(vecTw, vecDiff); + + vst1q(pIn0, vecSum); + pIn0 += 4; + vst1q(pIn1, vecCmplxTmp); + pIn1 += 4; + + blkCnt--; + } + + _arm_radix4_butterfly_inverse_f32_mve(S, pSrc, n2, onebyfftLen); + + _arm_radix4_butterfly_inverse_f32_mve(S, pSrc + fftLen, n2, onebyfftLen); +} + + +/** + @addtogroup ComplexFFTF32 + @{ + */ + +/** + @brief Processing function for the floating-point complex FFT. + @param[in] S points to an instance of the floating-point CFFT structure + @param[in,out] p1 points to the complex data buffer. Processing occurs in-place + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + */ + + +ARM_DSP_ATTRIBUTE void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * pSrc, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t fftLen = S->fftLen; + + if (ifftFlag == 1U) { + + switch (fftLen) { + case 16: + case 64: + case 256: + case 1024: + case 4096: + _arm_radix4_butterfly_inverse_f32_mve(S, pSrc, fftLen, arm_inverse_fft_length_f32(S->fftLen)); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_inverse_f32_mve(S, pSrc, fftLen); + break; + } + } else { + switch (fftLen) { + case 16: + case 64: + case 256: + case 1024: + case 4096: + _arm_radix4_butterfly_f32_mve(S, pSrc, fftLen); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_f32_mve(S, pSrc, fftLen); + break; + } + } + + + if (bitReverseFlag) + { + + arm_bitreversal_32_inpl_mve((uint32_t*)pSrc, S->bitRevLength, S->pBitRevTable); + + } +} + + +#elif defined(ARM_MATH_NEON) +#include "CMSIS_NE10_types.h" +#include "CMSIS_NE10_fft.h" + + + +ARM_DSP_ATTRIBUTE void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + const float32_t * pIn, + float32_t * pOut, + float32_t * pBuffer, /* When used, in is not modified */ + uint8_t ifftFlag) +{ + if (S->algorithm_flag == ARM_MIXED_RADIX_FFT) + { + if (ifftFlag) + { + arm_ne10_mixed_radix_generic_butterfly_inverse_float32_neon (S, + (ne10_fft_cpx_float32_t *)pIn, + (ne10_fft_cpx_float32_t *)pOut, + (ne10_fft_cpx_float32_t *)pBuffer); + } + else + { + arm_ne10_mixed_radix_generic_butterfly_float32_neon (S, + (ne10_fft_cpx_float32_t *)pIn, + (ne10_fft_cpx_float32_t *)pOut, + (ne10_fft_cpx_float32_t *)pBuffer); + } + } + else + { + if (ifftFlag == 0) + { + if (S->fftLen==16) + { + arm_ne10_fft16_forward_float32_neon (S, + (ne10_fft_cpx_float32_t *)pIn, + (ne10_fft_cpx_float32_t *)pOut + ); + } + else + { + arm_ne10_mixed_radix_fft_forward_float32_neon (S, + (ne10_fft_cpx_float32_t *)pIn, + (ne10_fft_cpx_float32_t *)pOut, + (ne10_fft_cpx_float32_t *)pBuffer); + } + } + else + { + if (S->fftLen==16) + { + arm_ne10_fft16_backward_float32_neon(S, + (ne10_fft_cpx_float32_t *)pIn, + (ne10_fft_cpx_float32_t *)pOut); + } + else + { + arm_ne10_mixed_radix_fft_backward_float32_neon (S, + (ne10_fft_cpx_float32_t *)pIn, + (ne10_fft_cpx_float32_t *)pOut, + (ne10_fft_cpx_float32_t *)pBuffer); + } + } + } +} +#else +extern void arm_radix8_butterfly_f32( + float32_t * pSrc, + uint16_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier); + +extern void arm_bitreversal_32( + uint32_t * pSrc, + const uint16_t bitRevLen, + const uint16_t * pBitRevTable); + +/** + @ingroup groupTransforms + */ + +/** + @defgroup ComplexFFT Complex FFT Functions + + @par + The Fast Fourier Transform (FFT) is an efficient algorithm for computing the + Discrete Fourier Transform (DFT). The FFT can be orders of magnitude faster + than the DFT, especially for long lengths. + The algorithms described in this section + operate on complex data. A separate set of functions is devoted to handling + of real sequences. + @par + There are separate algorithms for handling floating-point, Q15, and Q31 data + types. The algorithms available for each data type are described next. + @par + The FFT functions operate in-place. That is, the array holding the input data + will also be used to hold the corresponding result. The input data is complex + and contains <code>2*fftLen</code> interleaved values as shown below. + <pre>{real[0], imag[0], real[1], imag[1], ...} </pre> + The FFT result will be contained in the same array and the frequency domain + values will have the same interleaving. + + @par Floating-point + The floating-point complex FFT uses a mixed-radix algorithm. Multiple radix-8 + stages are performed along with a single radix-2 or radix-4 stage, as needed. + The algorithm supports lengths of [16, 32, 64, ..., 4096] and each length uses + a different twiddle factor table. + @par + The function uses the standard FFT definition and output values may grow by a + factor of <code>fftLen</code> when computing the forward transform. The + inverse transform includes a scale of <code>1/fftLen</code> as part of the + calculation and this matches the textbook definition of the inverse FFT. + @par + For the MVE version, the new arm_cfft_init_f32 initialization function is + <b>mandatory</b>. <b>Compilation flags are available to include only the required tables for the + needed FFTs.</b> Other FFT versions can continue to be initialized as + explained below. + @par + For versions not targeting Helium or Neon, pre-initialized data structures containing twiddle factors + and bit reversal tables are provided and defined in <code>arm_const_structs.h</code>. Include + this header in your function and then pass one of the constant structures as + an argument to arm_cfft_f32. For example: + @par + <code>arm_cfft_f32(arm_cfft_sR_f32_len64, pSrc, 1, 1)</code> + @par + computes a 64-point inverse complex FFT including bit reversal. + The data structures are treated as constant data and not modified during the + calculation. The same data structure can be reused for multiple transforms + including mixing forward and inverse transforms. + @par + Earlier releases of the library provided separate radix-2 and radix-4 + algorithms that operated on floating-point data. These functions are still + provided but are deprecated. The older functions are slower and less general + than the new functions. + @par + An example of initialization of the constants for the arm_cfft_f32 function follows: + @code + const static arm_cfft_instance_f32 *S; + ... + switch (length) { + case 16: + S = &arm_cfft_sR_f32_len16; + break; + case 32: + S = &arm_cfft_sR_f32_len32; + break; + case 64: + S = &arm_cfft_sR_f32_len64; + break; + case 128: + S = &arm_cfft_sR_f32_len128; + break; + case 256: + S = &arm_cfft_sR_f32_len256; + break; + case 512: + S = &arm_cfft_sR_f32_len512; + break; + case 1024: + S = &arm_cfft_sR_f32_len1024; + break; + case 2048: + S = &arm_cfft_sR_f32_len2048; + break; + case 4096: + S = &arm_cfft_sR_f32_len4096; + break; + } + @endcode + + @par + The new arm_cfft_init_f32 can also be used. + @par Q15 and Q31 + The floating-point complex FFT uses a mixed-radix algorithm. Multiple radix-4 + stages are performed along with a single radix-2 stage, as needed. + The algorithm supports lengths of [16, 32, 64, ..., 4096] and each length uses + a different twiddle factor table. + @par + The function uses the standard FFT definition and output values may grow by a + factor of <code>fftLen</code> when computing the forward transform. The + inverse transform includes a scale of <code>1/fftLen</code> as part of the + calculation and this matches the textbook definition of the inverse FFT. + @par + Pre-initialized data structures containing twiddle factors and bit reversal + tables are provided and defined in <code>arm_const_structs.h</code>. Include + this header in your function and then pass one of the constant structures as + an argument to arm_cfft_q31 (except if you are targeting Helium or Neon). For example: + @par + <code>arm_cfft_q31(arm_cfft_sR_q31_len64, pSrc, 1, 1)</code> + @par + computes a 64-point inverse complex FFT including bit reversal. + The data structures are treated as constant data and not modified during the + calculation. The same data structure can be reused for multiple transforms + including mixing forward and inverse transforms. + @par + Earlier releases of the library provided separate radix-2 and radix-4 + algorithms that operated on floating-point data. These functions are still + provided but are deprecated. The older functions are slower and less general + than the new functions. + @par + An example of initialization of the constants for the arm_cfft_q31 function follows: + @code + const static arm_cfft_instance_q31 *S; + ... + switch (length) { + case 16: + S = &arm_cfft_sR_q31_len16; + break; + case 32: + S = &arm_cfft_sR_q31_len32; + break; + case 64: + S = &arm_cfft_sR_q31_len64; + break; + case 128: + S = &arm_cfft_sR_q31_len128; + break; + case 256: + S = &arm_cfft_sR_q31_len256; + break; + case 512: + S = &arm_cfft_sR_q31_len512; + break; + case 1024: + S = &arm_cfft_sR_q31_len1024; + break; + case 2048: + S = &arm_cfft_sR_q31_len2048; + break; + case 4096: + S = &arm_cfft_sR_q31_len4096; + break; + } + @endcode + + @par Neon version + The neon version has a different API. + The input and output buffers must be + different. + There is a temporary buffer. + The bit reverse flag is not more + available in Neon version. + + @code + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + const float32_t * pIn, + float32_t * pOut, + float32_t * pBuffer, + uint8_t ifftFlag); + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + */ + +static void arm_cfft_radix8by2_f32 (arm_cfft_instance_f32 * S, float32_t * p1) +{ + uint32_t L = S->fftLen; + float32_t * pCol1, * pCol2, * pMid1, * pMid2; + float32_t * p2 = p1 + L; + const float32_t * tw = (float32_t *) S->pTwiddle; + float32_t t1[4], t2[4], t3[4], t4[4], twR, twI; + float32_t m0, m1, m2, m3; + uint32_t l; + + pCol1 = p1; + pCol2 = p2; + + /* Define new length */ + L >>= 1; + + /* Initialize mid pointers */ + pMid1 = p1 + L; + pMid2 = p2 + L; + + /* do two dot Fourier transform */ + for (l = L >> 2; l > 0; l-- ) + { + t1[0] = p1[0]; + t1[1] = p1[1]; + t1[2] = p1[2]; + t1[3] = p1[3]; + + t2[0] = p2[0]; + t2[1] = p2[1]; + t2[2] = p2[2]; + t2[3] = p2[3]; + + t3[0] = pMid1[0]; + t3[1] = pMid1[1]; + t3[2] = pMid1[2]; + t3[3] = pMid1[3]; + + t4[0] = pMid2[0]; + t4[1] = pMid2[1]; + t4[2] = pMid2[2]; + t4[3] = pMid2[3]; + + *p1++ = t1[0] + t2[0]; + *p1++ = t1[1] + t2[1]; + *p1++ = t1[2] + t2[2]; + *p1++ = t1[3] + t2[3]; /* col 1 */ + + t2[0] = t1[0] - t2[0]; + t2[1] = t1[1] - t2[1]; + t2[2] = t1[2] - t2[2]; + t2[3] = t1[3] - t2[3]; /* for col 2 */ + + *pMid1++ = t3[0] + t4[0]; + *pMid1++ = t3[1] + t4[1]; + *pMid1++ = t3[2] + t4[2]; + *pMid1++ = t3[3] + t4[3]; /* col 1 */ + + t4[0] = t4[0] - t3[0]; + t4[1] = t4[1] - t3[1]; + t4[2] = t4[2] - t3[2]; + t4[3] = t4[3] - t3[3]; /* for col 2 */ + + twR = *tw++; + twI = *tw++; + + /* multiply by twiddle factors */ + m0 = t2[0] * twR; + m1 = t2[1] * twI; + m2 = t2[1] * twR; + m3 = t2[0] * twI; + + /* R = R * Tr - I * Ti */ + *p2++ = m0 + m1; + /* I = I * Tr + R * Ti */ + *p2++ = m2 - m3; + + /* use vertical symmetry */ + /* 0.9988 - 0.0491i <==> -0.0491 - 0.9988i */ + m0 = t4[0] * twI; + m1 = t4[1] * twR; + m2 = t4[1] * twI; + m3 = t4[0] * twR; + + *pMid2++ = m0 - m1; + *pMid2++ = m2 + m3; + + twR = *tw++; + twI = *tw++; + + m0 = t2[2] * twR; + m1 = t2[3] * twI; + m2 = t2[3] * twR; + m3 = t2[2] * twI; + + *p2++ = m0 + m1; + *p2++ = m2 - m3; + + m0 = t4[2] * twI; + m1 = t4[3] * twR; + m2 = t4[3] * twI; + m3 = t4[2] * twR; + + *pMid2++ = m0 - m1; + *pMid2++ = m2 + m3; + } + + /* first col */ + arm_radix8_butterfly_f32 (pCol1, L, (float32_t *) S->pTwiddle, 2U); + + /* second col */ + arm_radix8_butterfly_f32 (pCol2, L, (float32_t *) S->pTwiddle, 2U); +} + +static void arm_cfft_radix8by4_f32 (arm_cfft_instance_f32 * S, float32_t * p1) +{ + uint32_t L = S->fftLen >> 1; + float32_t * pCol1, *pCol2, *pCol3, *pCol4, *pEnd1, *pEnd2, *pEnd3, *pEnd4; + const float32_t *tw2, *tw3, *tw4; + float32_t * p2 = p1 + L; + float32_t * p3 = p2 + L; + float32_t * p4 = p3 + L; + float32_t t2[4], t3[4], t4[4], twR, twI; + float32_t p1ap3_0, p1sp3_0, p1ap3_1, p1sp3_1; + float32_t m0, m1, m2, m3; + uint32_t l, twMod2, twMod3, twMod4; + + pCol1 = p1; /* points to real values by default */ + pCol2 = p2; + pCol3 = p3; + pCol4 = p4; + pEnd1 = p2 - 1; /* points to imaginary values by default */ + pEnd2 = p3 - 1; + pEnd3 = p4 - 1; + pEnd4 = pEnd3 + L; + + tw2 = tw3 = tw4 = (float32_t *) S->pTwiddle; + + L >>= 1; + + /* do four dot Fourier transform */ + + twMod2 = 2; + twMod3 = 4; + twMod4 = 6; + + /* TOP */ + p1ap3_0 = p1[0] + p3[0]; + p1sp3_0 = p1[0] - p3[0]; + p1ap3_1 = p1[1] + p3[1]; + p1sp3_1 = p1[1] - p3[1]; + + /* col 2 */ + t2[0] = p1sp3_0 + p2[1] - p4[1]; + t2[1] = p1sp3_1 - p2[0] + p4[0]; + /* col 3 */ + t3[0] = p1ap3_0 - p2[0] - p4[0]; + t3[1] = p1ap3_1 - p2[1] - p4[1]; + /* col 4 */ + t4[0] = p1sp3_0 - p2[1] + p4[1]; + t4[1] = p1sp3_1 + p2[0] - p4[0]; + /* col 1 */ + *p1++ = p1ap3_0 + p2[0] + p4[0]; + *p1++ = p1ap3_1 + p2[1] + p4[1]; + + /* Twiddle factors are ones */ + *p2++ = t2[0]; + *p2++ = t2[1]; + *p3++ = t3[0]; + *p3++ = t3[1]; + *p4++ = t4[0]; + *p4++ = t4[1]; + + tw2 += twMod2; + tw3 += twMod3; + tw4 += twMod4; + + for (l = (L - 2) >> 1; l > 0; l-- ) + { + /* TOP */ + p1ap3_0 = p1[0] + p3[0]; + p1sp3_0 = p1[0] - p3[0]; + p1ap3_1 = p1[1] + p3[1]; + p1sp3_1 = p1[1] - p3[1]; + /* col 2 */ + t2[0] = p1sp3_0 + p2[1] - p4[1]; + t2[1] = p1sp3_1 - p2[0] + p4[0]; + /* col 3 */ + t3[0] = p1ap3_0 - p2[0] - p4[0]; + t3[1] = p1ap3_1 - p2[1] - p4[1]; + /* col 4 */ + t4[0] = p1sp3_0 - p2[1] + p4[1]; + t4[1] = p1sp3_1 + p2[0] - p4[0]; + /* col 1 - top */ + *p1++ = p1ap3_0 + p2[0] + p4[0]; + *p1++ = p1ap3_1 + p2[1] + p4[1]; + + /* BOTTOM */ + p1ap3_1 = pEnd1[-1] + pEnd3[-1]; + p1sp3_1 = pEnd1[-1] - pEnd3[-1]; + p1ap3_0 = pEnd1[ 0] + pEnd3[0]; + p1sp3_0 = pEnd1[ 0] - pEnd3[0]; + /* col 2 */ + t2[2] = pEnd2[0] - pEnd4[0] + p1sp3_1; + t2[3] = pEnd1[0] - pEnd3[0] - pEnd2[-1] + pEnd4[-1]; + /* col 3 */ + t3[2] = p1ap3_1 - pEnd2[-1] - pEnd4[-1]; + t3[3] = p1ap3_0 - pEnd2[ 0] - pEnd4[ 0]; + /* col 4 */ + t4[2] = pEnd2[ 0] - pEnd4[ 0] - p1sp3_1; + t4[3] = pEnd4[-1] - pEnd2[-1] - p1sp3_0; + /* col 1 - Bottom */ + *pEnd1-- = p1ap3_0 + pEnd2[ 0] + pEnd4[ 0]; + *pEnd1-- = p1ap3_1 + pEnd2[-1] + pEnd4[-1]; + + /* COL 2 */ + /* read twiddle factors */ + twR = *tw2++; + twI = *tw2++; + /* multiply by twiddle factors */ + /* let Z1 = a + i(b), Z2 = c + i(d) */ + /* => Z1 * Z2 = (a*c - b*d) + i(b*c + a*d) */ + + /* Top */ + m0 = t2[0] * twR; + m1 = t2[1] * twI; + m2 = t2[1] * twR; + m3 = t2[0] * twI; + + *p2++ = m0 + m1; + *p2++ = m2 - m3; + /* use vertical symmetry col 2 */ + /* 0.9997 - 0.0245i <==> 0.0245 - 0.9997i */ + /* Bottom */ + m0 = t2[3] * twI; + m1 = t2[2] * twR; + m2 = t2[2] * twI; + m3 = t2[3] * twR; + + *pEnd2-- = m0 - m1; + *pEnd2-- = m2 + m3; + + /* COL 3 */ + twR = tw3[0]; + twI = tw3[1]; + tw3 += twMod3; + /* Top */ + m0 = t3[0] * twR; + m1 = t3[1] * twI; + m2 = t3[1] * twR; + m3 = t3[0] * twI; + + *p3++ = m0 + m1; + *p3++ = m2 - m3; + /* use vertical symmetry col 3 */ + /* 0.9988 - 0.0491i <==> -0.9988 - 0.0491i */ + /* Bottom */ + m0 = -t3[3] * twR; + m1 = t3[2] * twI; + m2 = t3[2] * twR; + m3 = t3[3] * twI; + + *pEnd3-- = m0 - m1; + *pEnd3-- = m3 - m2; + + /* COL 4 */ + twR = tw4[0]; + twI = tw4[1]; + tw4 += twMod4; + /* Top */ + m0 = t4[0] * twR; + m1 = t4[1] * twI; + m2 = t4[1] * twR; + m3 = t4[0] * twI; + + *p4++ = m0 + m1; + *p4++ = m2 - m3; + /* use vertical symmetry col 4 */ + /* 0.9973 - 0.0736i <==> -0.0736 + 0.9973i */ + /* Bottom */ + m0 = t4[3] * twI; + m1 = t4[2] * twR; + m2 = t4[2] * twI; + m3 = t4[3] * twR; + + *pEnd4-- = m0 - m1; + *pEnd4-- = m2 + m3; + } + + /* MIDDLE */ + /* Twiddle factors are */ + /* 1.0000 0.7071-0.7071i -1.0000i -0.7071-0.7071i */ + p1ap3_0 = p1[0] + p3[0]; + p1sp3_0 = p1[0] - p3[0]; + p1ap3_1 = p1[1] + p3[1]; + p1sp3_1 = p1[1] - p3[1]; + + /* col 2 */ + t2[0] = p1sp3_0 + p2[1] - p4[1]; + t2[1] = p1sp3_1 - p2[0] + p4[0]; + /* col 3 */ + t3[0] = p1ap3_0 - p2[0] - p4[0]; + t3[1] = p1ap3_1 - p2[1] - p4[1]; + /* col 4 */ + t4[0] = p1sp3_0 - p2[1] + p4[1]; + t4[1] = p1sp3_1 + p2[0] - p4[0]; + /* col 1 - Top */ + *p1++ = p1ap3_0 + p2[0] + p4[0]; + *p1++ = p1ap3_1 + p2[1] + p4[1]; + + /* COL 2 */ + twR = tw2[0]; + twI = tw2[1]; + + m0 = t2[0] * twR; + m1 = t2[1] * twI; + m2 = t2[1] * twR; + m3 = t2[0] * twI; + + *p2++ = m0 + m1; + *p2++ = m2 - m3; + /* COL 3 */ + twR = tw3[0]; + twI = tw3[1]; + + m0 = t3[0] * twR; + m1 = t3[1] * twI; + m2 = t3[1] * twR; + m3 = t3[0] * twI; + + *p3++ = m0 + m1; + *p3++ = m2 - m3; + /* COL 4 */ + twR = tw4[0]; + twI = tw4[1]; + + m0 = t4[0] * twR; + m1 = t4[1] * twI; + m2 = t4[1] * twR; + m3 = t4[0] * twI; + + *p4++ = m0 + m1; + *p4++ = m2 - m3; + + /* first col */ + arm_radix8_butterfly_f32 (pCol1, L, (float32_t *) S->pTwiddle, 4U); + + /* second col */ + arm_radix8_butterfly_f32 (pCol2, L, (float32_t *) S->pTwiddle, 4U); + + /* third col */ + arm_radix8_butterfly_f32 (pCol3, L, (float32_t *) S->pTwiddle, 4U); + + /* fourth col */ + arm_radix8_butterfly_f32 (pCol4, L, (float32_t *) S->pTwiddle, 4U); +} + +/** + @addtogroup ComplexFFTF32 + @{ + */ + +/** + @brief Processing function for the floating-point complex FFT. + @param[in] S points to an instance of the floating-point CFFT structure + @param[in,out] p1 points to the complex data buffer. Processing occurs in-place + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @par Neon version + The neon version has a different API. + The input and output buffers must be + different. + There is an optional temporary buffer. + If the temporary buffer is not used, the + input buffer is modified. + The bit reverse flag is not more + available in Neon version. + + @par + @code + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * pIn, + float32_t * pOut, + float32_t * pBuffer, + uint8_t ifftFlag); + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t L = S->fftLen, l; + float32_t invL, * pSrc; + + if (ifftFlag == 1U) + { + /* Conjugate input data */ + pSrc = p1 + 1; + for (l = 0; l < L; l++) + { + *pSrc = -*pSrc; + pSrc += 2; + } + } + + switch (L) + { + case 16: + case 128: + case 1024: + arm_cfft_radix8by2_f32 ( (arm_cfft_instance_f32 *) S, p1); + break; + case 32: + case 256: + case 2048: + arm_cfft_radix8by4_f32 ( (arm_cfft_instance_f32 *) S, p1); + break; + case 64: + case 512: + case 4096: + arm_radix8_butterfly_f32 ( p1, L, (float32_t *) S->pTwiddle, 1); + break; + } + + if ( bitReverseFlag ) + arm_bitreversal_32 ((uint32_t*) p1, S->bitRevLength, S->pBitRevTable); + + if (ifftFlag == 1U) + { + invL = 1.0f / (float32_t)L; + + /* Conjugate and scale output data */ + pSrc = p1; + for (l= 0; l < L; l++) + { + *pSrc++ *= invL ; + *pSrc = -(*pSrc) * invL; + pSrc++; + } + } +} +#endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */ + +/** + @} end of ComplexFFTF32 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f64.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f64.c new file mode 100755 index 0000000..4800165 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_f64.c @@ -0,0 +1,317 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_f64.c + * Description: Combined Radix Decimation in Frequency CFFT Double Precision Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + + +extern void arm_radix4_butterfly_f64( + float64_t * pSrc, + uint16_t fftLen, + const float64_t * pCoef, + uint16_t twidCoefModifier); + +extern void arm_bitreversal_64( + uint64_t * pSrc, + const uint16_t bitRevLen, + const uint16_t * pBitRevTable); + +/* ---------------------------------------------------------------------- + * Internal helper function used by the FFTs + * ---------------------------------------------------------------------- */ + +/* +* @brief Core function for the Double Precision floating-point CFFT butterfly process. +* @param[in, out] *pSrc points to the in-place buffer of F64 data type. +* @param[in] fftLen length of the FFT. +* @param[in] *pCoef points to the twiddle coefficient buffer. +* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. +*/ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_f64( + float64_t * pSrc, + uint16_t fftLen, + const float64_t * pCoef, + uint16_t twidCoefModifier) +{ + + float64_t co1, co2, co3, si1, si2, si3; + uint32_t ia1, ia2, ia3; + uint32_t i0, i1, i2, i3; + uint32_t n1, n2, j, k; + + float64_t t1, t2, r1, r2, s1, s2; + + + /* Initializations for the fft calculation */ + n2 = fftLen; + n1 = n2; + for (k = fftLen; k > 1U; k >>= 2U) + { + /* Initializations for the fft calculation */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* FFT Calculation */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* xa + xc */ + r1 = pSrc[(2U * i0)] + pSrc[(2U * i2)]; + + /* xa - xc */ + r2 = pSrc[(2U * i0)] - pSrc[(2U * i2)]; + + /* ya + yc */ + s1 = pSrc[(2U * i0) + 1U] + pSrc[(2U * i2) + 1U]; + + /* ya - yc */ + s2 = pSrc[(2U * i0) + 1U] - pSrc[(2U * i2) + 1U]; + + /* xb + xd */ + t1 = pSrc[2U * i1] + pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = r1 + t1; + + /* xa + xc -(xb + xd) */ + r1 = r1 - t1; + + /* yb + yd */ + t2 = pSrc[(2U * i1) + 1U] + pSrc[(2U * i3) + 1U]; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = s1 + t2; + + /* (ya + yc) - (yb + yd) */ + s1 = s1 - t2; + + /* (yb - yd) */ + t1 = pSrc[(2U * i1) + 1U] - pSrc[(2U * i3) + 1U]; + + /* (xb - xd) */ + t2 = pSrc[2U * i1] - pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = (r1 * co2) + (s1 * si2); + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = (s1 * co2) - (r1 * si2); + + /* (xa - xc) + (yb - yd) */ + r1 = r2 + t1; + + /* (xa - xc) - (yb - yd) */ + r2 = r2 - t1; + + /* (ya - yc) - (xb - xd) */ + s1 = s2 - t2; + + /* (ya - yc) + (xb - xd) */ + s2 = s2 + t2; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = (r1 * co1) + (s1 * si1); + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = (s1 * co1) - (r1 * si1); + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = (r2 * co3) + (s2 * si3); + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = (s2 * co3) - (r2 * si3); + + i0 += n1; + } while ( i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } +} + +/* +* @brief Core function for the Double Precision floating-point CFFT butterfly process. +* @param[in, out] *pSrc points to the in-place buffer of F64 data type. +* @param[in] fftLen length of the FFT. +* @param[in] *pCoef points to the twiddle coefficient buffer. +* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. +*/ + +static void arm_cfft_radix4by2_f64( + float64_t * pSrc, + uint32_t fftLen, + const float64_t * pCoef) +{ + uint32_t i, l; + uint32_t n2, ia; + float64_t xt, yt, cosVal, sinVal; + float64_t p0, p1,p2,p3,a0,a1; + + n2 = fftLen >> 1; + ia = 0; + for (i = 0; i < n2; i++) + { + cosVal = pCoef[2*ia]; + sinVal = pCoef[2*ia + 1]; + ia++; + + l = i + n2; + + /* Butterfly implementation */ + a0 = pSrc[2 * i] + pSrc[2 * l]; + xt = pSrc[2 * i] - pSrc[2 * l]; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1]; + + p0 = xt * cosVal; + p1 = yt * sinVal; + p2 = yt * cosVal; + p3 = xt * sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = p0 + p1; + pSrc[2 * l + 1] = p2 - p3; + + } + + // first col + arm_radix4_butterfly_f64( pSrc, n2, (float64_t*)pCoef, 2U); + // second col + arm_radix4_butterfly_f64( pSrc + fftLen, n2, (float64_t*)pCoef, 2U); + +} + +/** + @addtogroup ComplexFFTF64 + @{ + */ + +/** + @brief Processing function for the Double Precision floating-point complex FFT. + @param[in] S points to an instance of the Double Precision floating-point CFFT structure + @param[in,out] p1 points to the complex data buffer. Processing occurs in-place + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_f64( + const arm_cfft_instance_f64 * S, + float64_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t L = S->fftLen, l; + float64_t invL, * pSrc; + + if (ifftFlag == 1U) + { + /* Conjugate input data */ + pSrc = p1 + 1; + for(l=0; l<L; l++) + { + *pSrc = -*pSrc; + pSrc += 2; + } + } + + switch (L) + { + case 16: + case 64: + case 256: + case 1024: + case 4096: + arm_radix4_butterfly_f64 (p1, L, (float64_t*)S->pTwiddle, 1U); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_f64 ( p1, L, (float64_t*)S->pTwiddle); + break; + + } + + if ( bitReverseFlag ) + arm_bitreversal_64((uint64_t*)p1, S->bitRevLength,S->pBitRevTable); + + if (ifftFlag == 1U) + { + invL = 1.0 / (float64_t)L; + /* Conjugate and scale output data */ + pSrc = p1; + for(l=0; l<L; l++) + { + *pSrc++ *= invL ; + *pSrc = -(*pSrc) * invL; + pSrc++; + } + } +} + +/** + @} end of ComplexFFTF64 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f16.c new file mode 100755 index 0000000..49eb403 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f16.c @@ -0,0 +1,372 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_init_f16.c + * Description: Initialization function for cfft f16 instance + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + +/** + * @defgroup ComplexFFTF16 Complex FFT F16 + */ + +/** + @ingroup groupTransforms + */ + +/** + @addtogroup ComplexFFT + @{ + */ + +/** + @addtogroup ComplexFFTF16 + @{ + */ + + + +#include "dsp/transform_functions_f16.h" +#include "arm_common_tables_f16.h" +#include "arm_const_structs_f16.h" + + +#if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_vec_fft.h" +#include "arm_mve_tables_f16.h" + +#define CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F16(LEN) \ +static arm_status arm_cfft_radix4by2_rearrange_twiddles_##LEN##_f16(arm_cfft_instance_f16 *S)\ +{ \ + S->rearranged_twiddle_tab_stride1_arr = rearranged_twiddle_tab_stride1_arr_##LEN##_f16; \ + S->rearranged_twiddle_stride1 = rearranged_twiddle_stride1_##LEN##_f16; \ + \ + S->rearranged_twiddle_tab_stride2_arr = rearranged_twiddle_tab_stride2_arr_##LEN##_f16; \ + S->rearranged_twiddle_stride2 = rearranged_twiddle_stride2_##LEN##_f16; \ + \ + S->rearranged_twiddle_tab_stride3_arr = rearranged_twiddle_tab_stride3_arr_##LEN##_f16; \ + S->rearranged_twiddle_stride3 = rearranged_twiddle_stride3_##LEN##_f16; \ + return(ARM_MATH_SUCCESS); \ +} + +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F16(4096); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F16(1024); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F16(256); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F16(64); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F16(16); + + + +#define CFFTINIT_F16(LEN,LENTWIDDLE) \ +arm_status arm_cfft_init_##LEN##_f16( \ + arm_cfft_instance_f16 * S) \ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + /* Initialise the bit reversal table modifier */ \ + S->bitRevLength = ARMBITREVINDEXTABLE_FIXED_##LEN##_TABLE_LENGTH; \ + S->pBitRevTable = (uint16_t *)armBitRevIndexTable_fixed_##LEN; \ + S->pTwiddle = (float16_t *)twiddleCoefF16_##LEN; \ + status=arm_cfft_radix4by2_rearrange_twiddles_##LENTWIDDLE##_f16(S);\ + \ + return (status); \ +} + +#elif defined(ARM_MATH_NEON_FLOAT16) && defined(ARM_FLOAT16_SUPPORTED) +#include "arm_neon_tables_f16.h" + +#define CFFTINIT_F16(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_f16(arm_cfft_instance_f16 * S)\ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + S->pTwiddle = arm_neon_twiddles_##LEN##_f16; \ + S->factors=arm_neon_factors_##LEN##_f16; \ + S->fftLen = LEN; \ + S->algorithm_flag = 0; \ + S->last_twiddles = NULL; \ + return status; \ +} +#else + +#if defined(ARM_FLOAT16_SUPPORTED) + +#define FFTINIT(EXT,SIZE) \ + S->bitRevLength = arm_cfft_sR_##EXT##_len##SIZE.bitRevLength; \ + S->pBitRevTable = arm_cfft_sR_##EXT##_len##SIZE.pBitRevTable; \ + S->pTwiddle = arm_cfft_sR_##EXT##_len##SIZE.pTwiddle; + +#define CFFTINIT_F16(LEN,LENTWIDDLE) \ +arm_status arm_cfft_init_##LEN##_f16(arm_cfft_instance_f16 * S) \ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + /* Initializations of Instance structure depending on the FFT length */\ + FFTINIT(f16,LEN); \ + \ + return (status); \ +} + + +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ +#endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */ + +#if defined(ARM_MATH_MVE_FLOAT16) || defined(ARM_FLOAT16_SUPPORTED) +/** + @brief Initialization function for the cfft f16 function with 4096 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(4096,4096) + +/** + @brief Initialization function for the cfft f16 function with 2048 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(2048,1024) + + +/** + @brief Initialization function for the cfft f16 function with 1024 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(1024,1024) + + +/** + @brief Initialization function for the cfft f16 function with 512 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(512,256) + + +/** + @brief Initialization function for the cfft f16 function with 256 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(256,256) + + +/** + @brief Initialization function for the cfft f16 function with 128 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(128,64) + + +/** + @brief Initialization function for the cfft f16 function with 64 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(64,64) + + +/** + @brief Initialization function for the cfft f16 function with 32 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(32,16) + + +/** + @brief Initialization function for the cfft f16 function with 16 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F16(16,16) + + +/** + @brief Generic initialization function for the cfft f16 function + @param[in,out] S points to an instance of the floating-point CFFT structure + @param[in] fftLen fft length (number of complex samples) + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + + @par This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + */ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_f16( + arm_cfft_instance_f16 * S, + uint16_t fftLen) +{ + + /* Initialise the default arm status */ + arm_status status = ARM_MATH_SUCCESS; + + /* Initializations of Instance structure depending on the FFT length */ + switch (fftLen) { + /* Initializations of structure parameters for 4096 point FFT */ + case 4096U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_4096_f16(S); + break; + + /* Initializations of structure parameters for 2048 point FFT */ + case 2048U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_2048_f16(S); + break; + + /* Initializations of structure parameters for 1024 point FFT */ + case 1024U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_1024_f16(S); + break; + + /* Initializations of structure parameters for 512 point FFT */ + case 512U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_512_f16(S); + break; + + case 256U: + status=arm_cfft_init_256_f16(S); + break; + + case 128U: + status=arm_cfft_init_128_f16(S); + break; + + case 64U: + status=arm_cfft_init_64_f16(S); + break; + + case 32U: + status=arm_cfft_init_32_f16(S); + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + status=arm_cfft_init_16_f16(S); + break; + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + + return (status); +} +#endif /* Float 16 used*/ + +/** + @} end of ComplexFFTF16 group + */ + +/** + @} end of ComplexFFT group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f32.c new file mode 100755 index 0000000..56e552e --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f32.c @@ -0,0 +1,365 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_init_f32.c + * Description: Initialization function for cfft f32 instance + * + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2024 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +/** + * @defgroup ComplexFFTF32 Complex FFT F32 + */ + +/** + @ingroup groupTransforms + */ + +/** + @addtogroup ComplexFFT + @{ + */ + +/** + @addtogroup ComplexFFTF32 + @{ + */ +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" +#include "arm_const_structs.h" + + +#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_vec_fft.h" +#include "arm_mve_tables.h" + + +#define CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F32(LEN) \ +static arm_status arm_cfft_radix4by2_rearrange_twiddles_##LEN##_f32(arm_cfft_instance_f32 *S)\ +{ \ + S->rearranged_twiddle_tab_stride1_arr = rearranged_twiddle_tab_stride1_arr_##LEN##_f32; \ + S->rearranged_twiddle_stride1 = rearranged_twiddle_stride1_##LEN##_f32; \ + \ + S->rearranged_twiddle_tab_stride2_arr = rearranged_twiddle_tab_stride2_arr_##LEN##_f32; \ + S->rearranged_twiddle_stride2 = rearranged_twiddle_stride2_##LEN##_f32; \ + \ + S->rearranged_twiddle_tab_stride3_arr = rearranged_twiddle_tab_stride3_arr_##LEN##_f32; \ + S->rearranged_twiddle_stride3 = rearranged_twiddle_stride3_##LEN##_f32; \ + return(ARM_MATH_SUCCESS); \ +} + +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F32(4096); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F32(1024); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F32(256); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F32(64); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_F32(16); + + +#define CFFTINIT_F32(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_f32( \ + arm_cfft_instance_f32 * S) \ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + /* Initialise the bit reversal table modifier */ \ + S->bitRevLength = ARMBITREVINDEXTABLE_FIXED_##LEN##_TABLE_LENGTH; \ + S->pBitRevTable = (uint16_t *)armBitRevIndexTable_fixed_##LEN; \ + S->pTwiddle = (float32_t *)twiddleCoef_##LEN; \ + status=arm_cfft_radix4by2_rearrange_twiddles_##LENTWIDDLE##_f32(S); \ + \ + return (status); \ +} + +#elif defined(ARM_MATH_NEON) + +#include "arm_neon_tables.h" + +#define CFFTINIT_F32(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_f32(arm_cfft_instance_f32 * S)\ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + S->pTwiddle = arm_neon_twiddles_##LEN##_f32; \ + S->factors=arm_neon_factors_##LEN##_f32; \ + S->fftLen = LEN; \ + S->algorithm_flag = 0; \ + S->last_twiddles = NULL; \ + return status; \ +} +#else + +#define FFTINIT(EXT,SIZE) \ + S->bitRevLength = arm_cfft_sR_##EXT##_len##SIZE.bitRevLength; \ + S->pBitRevTable = arm_cfft_sR_##EXT##_len##SIZE.pBitRevTable; \ + S->pTwiddle = arm_cfft_sR_##EXT##_len##SIZE.pTwiddle; + +#define CFFTINIT_F32(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_f32(arm_cfft_instance_f32 * S)\ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + FFTINIT(f32,LEN); \ + \ + return (status); \ +} + +#endif /* if not neon and not mve*/ + + +/** + @brief Initialization function for the cfft f32 function with 4096 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(4096,4096) + + +/** + @brief Initialization function for the cfft f32 function with 2048 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(2048,1024) + + +/** + @brief Initialization function for the cfft f32 function with 1024 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(1024,1024) + + +/** + @brief Initialization function for the cfft f32 function with 512 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(512,256) + + +/** + @brief Initialization function for the cfft f32 function with 256 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(256,256) + + +/** + @brief Initialization function for the cfft f32 function with 128 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(128,64) + + +/** + @brief Initialization function for the cfft f32 function with 64 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(64,64) + + +/** + @brief Initialization function for the cfft f32 function with 32 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(32,16) + + +/** + @brief Initialization function for the cfft f32 function with 16 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F32(16,16) + + +/** + @brief Generic initialization function for the cfft f32 function + @param[in,out] S points to an instance of the floating-point CFFT structure + @param[in] fftLen fft length (number of complex samples) + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par + Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + */ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_f32( + arm_cfft_instance_f32 * S, + uint16_t fftLen) +{ + + /* Initialise the default arm status */ + arm_status status = ARM_MATH_SUCCESS; + + /* Initializations of Instance structure depending on the FFT length */ + switch (fftLen) { + /* Initializations of structure parameters for 4096 point FFT */ + case 4096U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_4096_f32(S); + break; + + /* Initializations of structure parameters for 2048 point FFT */ + case 2048U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_2048_f32(S); + break; + + /* Initializations of structure parameters for 1024 point FFT */ + case 1024U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_1024_f32(S); + break; + + /* Initializations of structure parameters for 512 point FFT */ + case 512U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_512_f32(S); + break; + + case 256U: + status=arm_cfft_init_256_f32(S); + break; + + case 128U: + status=arm_cfft_init_128_f32(S); + break; + + case 64U: + status=arm_cfft_init_64_f32(S); + break; + + case 32U: + status=arm_cfft_init_32_f32(S); + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + status=arm_cfft_init_16_f32(S); + break; + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + + return (status); +} + +/** + @} end of ComplexFFTF32 group + */ + +/** + @} end of ComplexFFT group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f64.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f64.c new file mode 100755 index 0000000..84a7b74 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_f64.c @@ -0,0 +1,289 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_init_f64.c + * Description: Initialization function for cfft f64 instance + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#define FFTINIT(EXT,SIZE) \ + S->bitRevLength = arm_cfft_sR_##EXT##_len##SIZE.bitRevLength; \ + S->pBitRevTable = arm_cfft_sR_##EXT##_len##SIZE.pBitRevTable; \ + S->pTwiddle = arm_cfft_sR_##EXT##_len##SIZE.pTwiddle; + +/** + * @defgroup ComplexFFTF64 Complex FFT F64 + */ + +/** + @ingroup groupTransforms + */ + +/** + @addtogroup ComplexFFT + @{ + */ + +/** + @addtogroup ComplexFFTF64 + @{ + */ + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" +#include "arm_const_structs.h" + + +#define CFFTINIT_F64(LEN) \ +arm_status arm_cfft_init_##LEN##_f64(arm_cfft_instance_f64 * S)\ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + FFTINIT(f64,LEN); \ + \ + return (status); \ +} + +/** + @brief Initialization function for the cfft f64 function with 4096 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(4096) + +/** + @brief Initialization function for the cfft f64 function with 2048 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(2048) + + +/** + @brief Initialization function for the cfft f64 function with 1024 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(1024) + +/** + @brief Initialization function for the cfft f64 function with 512 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(512) + +/** + @brief Initialization function for the cfft f64 function with 256 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(256) + +/** + @brief Initialization function for the cfft f64 function with 128 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(128) + +/** + @brief Initialization function for the cfft f64 function with 64 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(64) + +/** + @brief Initialization function for the cfft f64 function with 32 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(32) + +/** + @brief Initialization function for the cfft f64 function with 16 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_F64(16) + +/** + @brief Generic initialization function for the cfft f64 function + @param[in,out] S points to an instance of the floating-point CFFT structure + @param[in] fftLen fft length (number of complex samples) + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + + @par This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + + */ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_f64( + arm_cfft_instance_f64 * S, + uint16_t fftLen) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_SUCCESS; + + /* Initializations of Instance structure depending on the FFT length */ + switch (fftLen) { + /* Initializations of structure parameters for 4096 point FFT */ + case 4096U: + /* Initialise the bit reversal table modifier */ + status = arm_cfft_init_4096_f64(S); + break; + + /* Initializations of structure parameters for 2048 point FFT */ + case 2048U: + /* Initialise the bit reversal table modifier */ + status = arm_cfft_init_2048_f64(S); + + break; + + /* Initializations of structure parameters for 1024 point FFT */ + case 1024U: + /* Initialise the bit reversal table modifier */ + status = arm_cfft_init_1024_f64(S); + + break; + + /* Initializations of structure parameters for 512 point FFT */ + case 512U: + /* Initialise the bit reversal table modifier */ + status = arm_cfft_init_512_f64(S); + break; + + case 256U: + status = arm_cfft_init_256_f64(S); + break; + + case 128U: + status = arm_cfft_init_128_f64(S); + break; + + case 64U: + status = arm_cfft_init_64_f64(S); + break; + + case 32U: + status = arm_cfft_init_32_f64(S); + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + status = arm_cfft_init_16_f64(S); + break; + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + + return (status); +} +/** + @} end of ComplexFFTF64 group + */ + +/** + @} end of ComplexFFT group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_q15.c new file mode 100755 index 0000000..f1be0ae --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_q15.c @@ -0,0 +1,356 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_init_q15.c + * Description: Initialization function for cfft q15 instance + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + +/** + * @defgroup ComplexFFTQ15 Complex FFT Q15 + */ + +/** + @ingroup groupTransforms + */ + +/** + @addtogroup ComplexFFT + @{ + */ + +/** + @addtogroup ComplexFFTQ15 + @{ + */ +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" +#include "arm_const_structs.h" + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_vec_fft.h" +#include "arm_mve_tables.h" + +#define CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q15(LEN) \ +static arm_status arm_cfft_radix4by2_rearrange_twiddles_##LEN##_q15(arm_cfft_instance_q15 *S)\ +{ \ + S->rearranged_twiddle_tab_stride1_arr = rearranged_twiddle_tab_stride1_arr_##LEN##_q15; \ + S->rearranged_twiddle_stride1 = rearranged_twiddle_stride1_##LEN##_q15; \ + \ + S->rearranged_twiddle_tab_stride2_arr = rearranged_twiddle_tab_stride2_arr_##LEN##_q15; \ + S->rearranged_twiddle_stride2 = rearranged_twiddle_stride2_##LEN##_q15; \ + \ + S->rearranged_twiddle_tab_stride3_arr = rearranged_twiddle_tab_stride3_arr_##LEN##_q15; \ + S->rearranged_twiddle_stride3 = rearranged_twiddle_stride3_##LEN##_q15; \ + return(ARM_MATH_SUCCESS); \ +} + +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q15(4096); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q15(1024); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q15(256); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q15(64); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q15(16); + + +#define CFFTINIT_Q15(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_q15( \ + arm_cfft_instance_q15 * S) \ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + /* Initialise the bit reversal table modifier */ \ + S->bitRevLength = ARMBITREVINDEXTABLE_FIXED_##LEN##_TABLE_LENGTH; \ + S->pBitRevTable = (uint16_t *)armBitRevIndexTable_fixed_##LEN; \ + S->pTwiddle = (q15_t *)twiddleCoef_##LEN##_q15; \ + status=arm_cfft_radix4by2_rearrange_twiddles_##LENTWIDDLE##_q15(S);\ + \ + return (status); \ +} + +#elif defined(ARM_MATH_NEON) + +#include "arm_neon_tables.h" + +#define CFFTINIT_Q15(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_q15(\ + arm_cfft_instance_q15 * S) \ +{ \ + arm_status status = ARM_MATH_SUCCESS; \ + S->pTwiddle = arm_neon_twiddles_##LEN##_q15; \ + S->factors=arm_neon_factors_##LEN##_q15; \ + S->fftLen = LEN; \ + S->algorithm_flag = 0; \ + S->last_twiddles = NULL; \ + return (status); \ +} +#else + +#define FFTINIT(EXT,SIZE) \ + S->bitRevLength = arm_cfft_sR_##EXT##_len##SIZE.bitRevLength;\ + S->pBitRevTable = arm_cfft_sR_##EXT##_len##SIZE.pBitRevTable;\ + S->pTwiddle = arm_cfft_sR_##EXT##_len##SIZE.pTwiddle; + +#define CFFTINIT_Q15(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_q15(arm_cfft_instance_q15 * S)\ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + FFTINIT(q15,LEN); \ + \ + return (status); \ +} + +#endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */ + + + +/** + @brief Initialization function for the cfft q15 function for 4096 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(4096,4096) + +/** + @brief Initialization function for the cfft q15 function for 2048 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(2048,1024) + +/** + @brief Initialization function for the cfft q15 function for 1024 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(1024,1024) + +/** + @brief Initialization function for the cfft q15 function for 512 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(512,256) + +/** + @brief Initialization function for the cfft q15 function for 256 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(256,256) + +/** + @brief Initialization function for the cfft q15 function for 128 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(128,64) + +/** + @brief Initialization function for the cfft q15 function for 64 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(64,64) + +/** + @brief Initialization function for the cfft q15 function for 32 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(32,16) + +/** + @brief Initialization function for the cfft q15 function for 16 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q15(16,16) + +/** + @brief Generic initialization function for the cfft q15 function + @param[in,out] S points to an instance of the floating-point CFFT structure + @param[in] fftLen fft length (number of complex samples) + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + */ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_q15( + arm_cfft_instance_q15 * S, + uint16_t fftLen) +{ + + /* Initialise the default arm status */ + arm_status status = ARM_MATH_SUCCESS; + + /* Initializations of Instance structure depending on the FFT length */ + switch (fftLen) { + /* Initializations of structure parameters for 4096 point FFT */ + case 4096U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_4096_q15(S); + break; + + /* Initializations of structure parameters for 2048 point FFT */ + case 2048U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_2048_q15(S); + break; + + /* Initializations of structure parameters for 1024 point FFT */ + case 1024U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_1024_q15(S); + break; + + /* Initializations of structure parameters for 512 point FFT */ + case 512U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_512_q15(S); + break; + + case 256U: + status=arm_cfft_init_256_q15(S); + break; + + case 128U: + status=arm_cfft_init_128_q15(S); + break; + + case 64U: + status=arm_cfft_init_64_q15(S); + break; + + case 32U: + status=arm_cfft_init_32_q15(S); + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + status=arm_cfft_init_16_q15(S); + break; + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + + return (status); +} +/** + @} end of ComplexFFTQ15 group + */ + +/** + @} end of ComplexFFT group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_q31.c new file mode 100755 index 0000000..d37876b --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_init_q31.c @@ -0,0 +1,359 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_init_q31.c + * Description: Initialization function for cfft q31 instance + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + +/** + * @defgroup ComplexFFTQ31 Complex FFT Q31 + */ + +/** + @ingroup groupTransforms + */ + +/** + @addtogroup ComplexFFT + @{ + */ + +/** + @addtogroup ComplexFFTQ31 + @{ + */ + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" +#include "arm_const_structs.h" + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_vec_fft.h" +#include "arm_mve_tables.h" + +#define CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q31(LEN) \ +static arm_status arm_cfft_radix4by2_rearrange_twiddles_##LEN##_q31(arm_cfft_instance_q31 *S)\ +{ \ + S->rearranged_twiddle_tab_stride1_arr = rearranged_twiddle_tab_stride1_arr_##LEN##_q31; \ + S->rearranged_twiddle_stride1 = rearranged_twiddle_stride1_##LEN##_q31; \ + \ + S->rearranged_twiddle_tab_stride2_arr = rearranged_twiddle_tab_stride2_arr_##LEN##_q31; \ + S->rearranged_twiddle_stride2 = rearranged_twiddle_stride2_##LEN##_q31; \ + \ + S->rearranged_twiddle_tab_stride3_arr = rearranged_twiddle_tab_stride3_arr_##LEN##_q31; \ + S->rearranged_twiddle_stride3 = rearranged_twiddle_stride3_##LEN##_q31; \ + return(ARM_MATH_SUCCESS); \ +} + +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q31(4096); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q31(1024); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q31(256); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q31(64); +CFFT_RADIX4BY2_REARRANGE_TWIDDLES_Q31(16); + + +#define CFFTINIT_Q31(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_q31( \ + arm_cfft_instance_q31 * S) \ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + /* Initialise the bit reversal table modifier */ \ + S->bitRevLength = ARMBITREVINDEXTABLE_FIXED_##LEN##_TABLE_LENGTH; \ + S->pBitRevTable = (uint16_t *)armBitRevIndexTable_fixed_##LEN; \ + S->pTwiddle = (q31_t *)twiddleCoef_##LEN##_q31; \ + status=arm_cfft_radix4by2_rearrange_twiddles_##LENTWIDDLE##_q31(S);\ + \ + return (status); \ +} + +#elif defined(ARM_MATH_NEON) + +#include "arm_neon_tables.h" + +#define CFFTINIT_Q31(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_q31(\ + arm_cfft_instance_q31 * S) \ +{ \ + arm_status status = ARM_MATH_SUCCESS; \ + S->pTwiddle = arm_neon_twiddles_##LEN##_q31; \ + S->factors=arm_neon_factors_##LEN##_q31; \ + S->fftLen = LEN; \ + S->algorithm_flag = 0; \ + S->last_twiddles = NULL; \ + return (status); \ +} + +#else + +#define FFTINIT(EXT,SIZE) \ + S->bitRevLength = arm_cfft_sR_##EXT##_len##SIZE.bitRevLength; \ + S->pBitRevTable = arm_cfft_sR_##EXT##_len##SIZE.pBitRevTable; \ + S->pTwiddle = arm_cfft_sR_##EXT##_len##SIZE.pTwiddle; + +#define CFFTINIT_Q31(LEN,LENTWIDDLE) \ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_##LEN##_q31(arm_cfft_instance_q31 * S)\ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialise the FFT length */ \ + S->fftLen = LEN; \ + \ + /* Initialise the Twiddle coefficient pointer */ \ + S->pTwiddle = NULL; \ + \ + FFTINIT(q31,LEN); \ + \ + return (status); \ +} + + +#endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */ + +/** + @brief Initialization function for the cfft q31 function for 4096 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(4096,4096) + +/** + @brief Initialization function for the cfft q31 function for 2048 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(2048,1024) + +/** + @brief Initialization function for the cfft q31 function for 1024 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(1024,1024) + +/** + @brief Initialization function for the cfft q31 function for 512 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(512,256) + +/** + @brief Initialization function for the cfft q31 function for 256 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(256,256) + +/** + @brief Initialization function for the cfft q31 function for 128 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(128,64) + +/** + @brief Initialization function for the cfft q31 function for 64 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(64,64) + +/** + @brief Initialization function for the cfft q31 function for 32 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(32,16) + +/** + @brief Initialization function for the cfft q31 function for 16 samples + @param[in,out] S points to an instance of the floating-point CFFT structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + */ +CFFTINIT_Q31(16,16) + +/** + @brief Generic initialization function for the cfft q31 function + @param[in,out] S points to an instance of the floating-point CFFT structure + @param[in] fftLen fft length (number of complex samples) + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + + @par Use of this function is mandatory only for the Helium and Neon versions of the FFT. + Other versions can still initialize directly the data structure using + variables declared in arm_const_structs.h + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + */ +ARM_DSP_ATTRIBUTE arm_status arm_cfft_init_q31( + arm_cfft_instance_q31 * S, + uint16_t fftLen) +{ + + /* Initialise the default arm status */ + arm_status status = ARM_MATH_SUCCESS; + + + + /* Initializations of Instance structure depending on the FFT length */ + switch (fftLen) { + /* Initializations of structure parameters for 4096 point FFT */ + case 4096U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_4096_q31(S); + break; + + /* Initializations of structure parameters for 2048 point FFT */ + case 2048U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_2048_q31(S); + break; + + /* Initializations of structure parameters for 1024 point FFT */ + case 1024U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_1024_q31(S); + break; + + /* Initializations of structure parameters for 512 point FFT */ + case 512U: + /* Initialise the bit reversal table modifier */ + status=arm_cfft_init_512_q31(S); + break; + + case 256U: + status=arm_cfft_init_256_q31(S); + break; + + case 128U: + status=arm_cfft_init_128_q31(S); + break; + + case 64U: + status=arm_cfft_init_64_q31(S); + break; + + case 32U: + status=arm_cfft_init_32_q31(S); + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + status=arm_cfft_init_16_q31(S); + break; + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + + return (status); +} +/** + @} end of ComplexFFTQ31 group + */ + +/** + @} end of ComplexFFT group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_q15.c new file mode 100755 index 0000000..5244a36 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_q15.c @@ -0,0 +1,932 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_q15.c + * Description: Combined Radix Decimation in Q15 Frequency CFFT processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_vec_fft.h" + + +static void _arm_radix4_butterfly_q15_mve( + const arm_cfft_instance_q15 * S, + q15_t *pSrc, + uint32_t fftLen) +{ + q15x8_t vecTmp0, vecTmp1; + q15x8_t vecSum0, vecDiff0, vecSum1, vecDiff1; + q15x8_t vecA, vecB, vecC, vecD; + uint32_t blkCnt; + uint32_t n1, n2; + uint32_t stage = 0; + int32_t iter = 1; + static const int32_t strides[4] = { + (0 - 16) * (int32_t)sizeof(q15_t *), (4 - 16) * (int32_t)sizeof(q15_t *), + (8 - 16) * (int32_t)sizeof(q15_t *), (12 - 16) * (int32_t)sizeof(q15_t *) + }; + + /* + * Process first stages + * Each stage in middle stages provides two down scaling of the input + */ + n2 = fftLen; + n1 = n2; + n2 >>= 2u; + + for (int k = fftLen / 4u; k > 1; k >>= 2u) + { + q15_t const *p_rearranged_twiddle_tab_stride2 = + &S->rearranged_twiddle_stride2[ + S->rearranged_twiddle_tab_stride2_arr[stage]]; + q15_t const *p_rearranged_twiddle_tab_stride3 = &S->rearranged_twiddle_stride3[ + S->rearranged_twiddle_tab_stride3_arr[stage]]; + q15_t const *p_rearranged_twiddle_tab_stride1 = + &S->rearranged_twiddle_stride1[ + S->rearranged_twiddle_tab_stride1_arr[stage]]; + + q15_t * pBase = pSrc; + for (int i = 0; i < iter; i++) + { + q15_t *inA = pBase; + q15_t *inB = inA + n2 * CMPLX_DIM; + q15_t *inC = inB + n2 * CMPLX_DIM; + q15_t *inD = inC + n2 * CMPLX_DIM; + q15_t const *pW1 = p_rearranged_twiddle_tab_stride1; + q15_t const *pW2 = p_rearranged_twiddle_tab_stride2; + q15_t const *pW3 = p_rearranged_twiddle_tab_stride3; + q15x8_t vecW; + + blkCnt = n2 / 4; + /* + * load 4 x q15 complex pair + */ + vecA = vldrhq_s16(inA); + vecC = vldrhq_s16(inC); + while (blkCnt > 0U) + { + vecB = vldrhq_s16(inB); + vecD = vldrhq_s16(inD); + + vecSum0 = vhaddq(vecA, vecC); + vecDiff0 = vhsubq(vecA, vecC); + + vecSum1 = vhaddq(vecB, vecD); + vecDiff1 = vhsubq(vecB, vecD); + /* + * [ 1 1 1 1 ] * [ A B C D ]' .* 1 + */ + vecTmp0 = vhaddq(vecSum0, vecSum1); + vst1q(inA, vecTmp0); + inA += 8; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]' + */ + vecTmp0 = vhsubq(vecSum0, vecSum1); + /* + * [ 1 -1 1 -1 ] * [ A B C D ]'.* W2 + */ + vecW = vld1q(pW2); + pW2 += 8; + vecTmp1 = MVE_CMPLX_MULT_FX_AxB(vecW, vecTmp0, q15x8_t); + + vst1q(inB, vecTmp1); + inB += 8; + /* + * [ 1 -i -1 +i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 -i -1 +i ] * [ A B C D ]'.* W1 + */ + vecW = vld1q(pW1); + pW1 += 8; + vecTmp1 = MVE_CMPLX_MULT_FX_AxB(vecW, vecTmp0, q15x8_t); + vst1q(inC, vecTmp1); + inC += 8; + + /* + * [ 1 +i -1 -i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 +i -1 -i ] * [ A B C D ]'.* W3 + */ + vecW = vld1q(pW3); + pW3 += 8; + vecTmp1 = MVE_CMPLX_MULT_FX_AxB(vecW, vecTmp0, q15x8_t); + vst1q(inD, vecTmp1); + inD += 8; + + vecA = vldrhq_s16(inA); + vecC = vldrhq_s16(inC); + + blkCnt--; + } + pBase += CMPLX_DIM * n1; + } + n1 = n2; + n2 >>= 2u; + iter = iter << 2; + stage++; + } + + /* + * start of Last stage process + */ + uint32x4_t vecScGathAddr = vld1q_u32 ((uint32_t*)strides); + vecScGathAddr = vecScGathAddr + (uint32_t) pSrc; + + /* + * load scheduling + */ + vecA = (q15x8_t) vldrwq_gather_base_wb_s32(&vecScGathAddr, 64); + vecC = (q15x8_t) vldrwq_gather_base_s32(vecScGathAddr, 8); + + blkCnt = (fftLen >> 4); + while (blkCnt > 0U) + { + vecSum0 = vhaddq(vecA, vecC); + vecDiff0 = vhsubq(vecA, vecC); + + vecB = (q15x8_t) vldrwq_gather_base_s32(vecScGathAddr, 4); + vecD = (q15x8_t) vldrwq_gather_base_s32(vecScGathAddr, 12); + + vecSum1 = vhaddq(vecB, vecD); + vecDiff1 = vhsubq(vecB, vecD); + /* + * pre-load for next iteration + */ + vecA = (q15x8_t) vldrwq_gather_base_wb_s32(&vecScGathAddr, 64); + vecC = (q15x8_t) vldrwq_gather_base_s32(vecScGathAddr, 8); + + vecTmp0 = vhaddq(vecSum0, vecSum1); + vstrwq_scatter_base_s32(vecScGathAddr, -64, (int32x4_t) vecTmp0); + + vecTmp0 = vhsubq(vecSum0, vecSum1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 4, (int32x4_t) vecTmp0); + + vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 8, (int32x4_t) vecTmp0); + + vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 12, (int32x4_t) vecTmp0); + + blkCnt--; + } + +} + +static void arm_cfft_radix4by2_q15_mve(const arm_cfft_instance_q15 *S, q15_t *pSrc, uint32_t fftLen) +{ + uint32_t n2; + q15_t *pIn0; + q15_t *pIn1; + const q15_t *pCoef = S->pTwiddle; + uint32_t blkCnt; + q15x8_t vecIn0, vecIn1, vecSum, vecDiff; + q15x8_t vecCmplxTmp, vecTw; + q15_t const *pCoefVec; + + n2 = fftLen >> 1; + + pIn0 = pSrc; + pIn1 = pSrc + fftLen; + pCoefVec = pCoef; + + blkCnt = n2 / 4; + + while (blkCnt > 0U) + { + vecIn0 = *(q15x8_t *) pIn0; + vecIn1 = *(q15x8_t *) pIn1; + + vecIn0 = vecIn0 >> 1; + vecIn1 = vecIn1 >> 1; + vecSum = vhaddq(vecIn0, vecIn1); + vst1q(pIn0, vecSum); + pIn0 += 8; + + vecTw = vld1q(pCoefVec); + pCoefVec += 8; + + vecDiff = vhsubq(vecIn0, vecIn1); + vecCmplxTmp = MVE_CMPLX_MULT_FX_AxConjB(vecDiff, vecTw, q15x8_t); + vst1q(pIn1, vecCmplxTmp); + pIn1 += 8; + + blkCnt--; + } + + _arm_radix4_butterfly_q15_mve(S, pSrc, n2); + + _arm_radix4_butterfly_q15_mve(S, pSrc + fftLen, n2); + + + pIn0 = pSrc; + blkCnt = (fftLen << 1) >> 3; + while (blkCnt > 0U) + { + vecIn0 = *(q15x8_t *) pIn0; + vecIn0 = vecIn0 << 1; + vst1q(pIn0, vecIn0); + pIn0 += 8; + blkCnt--; + } + /* + * tail + * (will be merged thru tail predication) + */ + blkCnt = (fftLen << 1) & 7; + if (blkCnt > 0U) + { + mve_pred16_t p0 = vctp16q(blkCnt); + + vecIn0 = *(q15x8_t *) pIn0; + vecIn0 = vecIn0 << 1; + vstrhq_p(pIn0, vecIn0, p0); + } +} + +static void _arm_radix4_butterfly_inverse_q15_mve(const arm_cfft_instance_q15 *S,q15_t *pSrc, uint32_t fftLen) +{ + q15x8_t vecTmp0, vecTmp1; + q15x8_t vecSum0, vecDiff0, vecSum1, vecDiff1; + q15x8_t vecA, vecB, vecC, vecD; + uint32_t blkCnt; + uint32_t n1, n2; + uint32_t stage = 0; + int32_t iter = 1; + static const int32_t strides[4] = { + (0 - 16) * (int32_t)sizeof(q15_t *), (4 - 16) * (int32_t)sizeof(q15_t *), + (8 - 16) * (int32_t)sizeof(q15_t *), (12 - 16) * (int32_t)sizeof(q15_t *) + }; + + + /* + * Process first stages + * Each stage in middle stages provides two down scaling of the input + */ + n2 = fftLen; + n1 = n2; + n2 >>= 2u; + + for (int k = fftLen / 4u; k > 1; k >>= 2u) + { + q15_t const *p_rearranged_twiddle_tab_stride2 = + &S->rearranged_twiddle_stride2[ + S->rearranged_twiddle_tab_stride2_arr[stage]]; + q15_t const *p_rearranged_twiddle_tab_stride3 = &S->rearranged_twiddle_stride3[ + S->rearranged_twiddle_tab_stride3_arr[stage]]; + q15_t const *p_rearranged_twiddle_tab_stride1 = + &S->rearranged_twiddle_stride1[ + S->rearranged_twiddle_tab_stride1_arr[stage]]; + + q15_t * pBase = pSrc; + for (int i = 0; i < iter; i++) + { + q15_t *inA = pBase; + q15_t *inB = inA + n2 * CMPLX_DIM; + q15_t *inC = inB + n2 * CMPLX_DIM; + q15_t *inD = inC + n2 * CMPLX_DIM; + q15_t const *pW1 = p_rearranged_twiddle_tab_stride1; + q15_t const *pW2 = p_rearranged_twiddle_tab_stride2; + q15_t const *pW3 = p_rearranged_twiddle_tab_stride3; + q15x8_t vecW; + + + blkCnt = n2 / 4; + /* + * load 4 x q15 complex pair + */ + vecA = vldrhq_s16(inA); + vecC = vldrhq_s16(inC); + while (blkCnt > 0U) + { + vecB = vldrhq_s16(inB); + vecD = vldrhq_s16(inD); + + vecSum0 = vhaddq(vecA, vecC); + vecDiff0 = vhsubq(vecA, vecC); + + vecSum1 = vhaddq(vecB, vecD); + vecDiff1 = vhsubq(vecB, vecD); + /* + * [ 1 1 1 1 ] * [ A B C D ]' .* 1 + */ + vecTmp0 = vhaddq(vecSum0, vecSum1); + vst1q(inA, vecTmp0); + inA += 8; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]' + */ + vecTmp0 = vhsubq(vecSum0, vecSum1); + /* + * [ 1 -1 1 -1 ] * [ A B C D ]'.* W2 + */ + vecW = vld1q(pW2); + pW2 += 8; + vecTmp1 = MVE_CMPLX_MULT_FX_AxConjB(vecTmp0, vecW, q15x8_t); + + vst1q(inB, vecTmp1); + inB += 8; + /* + * [ 1 -i -1 +i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 -i -1 +i ] * [ A B C D ]'.* W1 + */ + vecW = vld1q(pW1); + pW1 += 8; + vecTmp1 = MVE_CMPLX_MULT_FX_AxConjB(vecTmp0, vecW, q15x8_t); + vst1q(inC, vecTmp1); + inC += 8; + /* + * [ 1 +i -1 -i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 +i -1 -i ] * [ A B C D ]'.* W3 + */ + vecW = vld1q(pW3); + pW3 += 8; + vecTmp1 = MVE_CMPLX_MULT_FX_AxConjB(vecTmp0, vecW, q15x8_t); + vst1q(inD, vecTmp1); + inD += 8; + + vecA = vldrhq_s16(inA); + vecC = vldrhq_s16(inC); + + blkCnt--; + } + pBase += CMPLX_DIM * n1; + } + n1 = n2; + n2 >>= 2u; + iter = iter << 2; + stage++; + } + + /* + * start of Last stage process + */ + uint32x4_t vecScGathAddr = vld1q_u32((uint32_t*)strides); + vecScGathAddr = vecScGathAddr + (uint32_t) pSrc; + + /* + * load scheduling + */ + vecA = (q15x8_t) vldrwq_gather_base_wb_s32(&vecScGathAddr, 64); + vecC = (q15x8_t) vldrwq_gather_base_s32(vecScGathAddr, 8); + + blkCnt = (fftLen >> 4); + while (blkCnt > 0U) + { + vecSum0 = vhaddq(vecA, vecC); + vecDiff0 = vhsubq(vecA, vecC); + + vecB = (q15x8_t) vldrwq_gather_base_s32(vecScGathAddr, 4); + vecD = (q15x8_t) vldrwq_gather_base_s32(vecScGathAddr, 12); + + vecSum1 = vhaddq(vecB, vecD); + vecDiff1 = vhsubq(vecB, vecD); + /* + * pre-load for next iteration + */ + vecA = (q15x8_t) vldrwq_gather_base_wb_s32(&vecScGathAddr, 64); + vecC = (q15x8_t) vldrwq_gather_base_s32(vecScGathAddr, 8); + + vecTmp0 = vhaddq(vecSum0, vecSum1); + vstrwq_scatter_base_s32(vecScGathAddr, -64, (int32x4_t) vecTmp0); + + vecTmp0 = vhsubq(vecSum0, vecSum1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 4, (int32x4_t) vecTmp0); + + vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 8, (int32x4_t) vecTmp0); + + vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 12, (int32x4_t) vecTmp0); + + blkCnt--; + } +} + +static void arm_cfft_radix4by2_inverse_q15_mve(const arm_cfft_instance_q15 *S, q15_t *pSrc, uint32_t fftLen) +{ + uint32_t n2; + q15_t *pIn0; + q15_t *pIn1; + const q15_t *pCoef = S->pTwiddle; + + uint32_t blkCnt; + q15x8_t vecIn0, vecIn1, vecSum, vecDiff; + q15x8_t vecCmplxTmp, vecTw; + q15_t const *pCoefVec; + + n2 = fftLen >> 1; + + pIn0 = pSrc; + pIn1 = pSrc + fftLen; + pCoefVec = pCoef; + + blkCnt = n2 / 4; + + while (blkCnt > 0U) + { + vecIn0 = *(q15x8_t *) pIn0; + vecIn1 = *(q15x8_t *) pIn1; + + vecIn0 = vecIn0 >> 1; + vecIn1 = vecIn1 >> 1; + vecSum = vhaddq(vecIn0, vecIn1); + vst1q(pIn0, vecSum); + pIn0 += 8; + + vecTw = vld1q(pCoefVec); + pCoefVec += 8; + + vecDiff = vhsubq(vecIn0, vecIn1); + vecCmplxTmp = vqrdmlsdhq(vuninitializedq_s16() , vecDiff, vecTw); + vecCmplxTmp = vqrdmladhxq(vecCmplxTmp, vecDiff, vecTw); + vst1q(pIn1, vecCmplxTmp); + pIn1 += 8; + + blkCnt--; + } + + + _arm_radix4_butterfly_inverse_q15_mve(S, pSrc, n2); + + _arm_radix4_butterfly_inverse_q15_mve(S, pSrc + fftLen, n2); + + pIn0 = pSrc; + blkCnt = (fftLen << 1) >> 3; + while (blkCnt > 0U) + { + vecIn0 = *(q15x8_t *) pIn0; + vecIn0 = vecIn0 << 1; + vst1q(pIn0, vecIn0); + pIn0 += 8; + blkCnt--; + } + /* + * tail + * (will be merged thru tail predication) + */ + blkCnt = (fftLen << 1) & 7; + while (blkCnt > 0U) + { + mve_pred16_t p0 = vctp16q(blkCnt); + + vecIn0 = *(q15x8_t *) pIn0; + vecIn0 = vecIn0 << 1; + vstrhq_p(pIn0, vecIn0, p0); + } +} + +ARM_DSP_ATTRIBUTE void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * pSrc, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t fftLen = S->fftLen; + + if (ifftFlag == 1U) { + + switch (fftLen) { + case 16: + case 64: + case 256: + case 1024: + case 4096: + _arm_radix4_butterfly_inverse_q15_mve(S, pSrc, fftLen); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_inverse_q15_mve(S, pSrc, fftLen); + break; + } + } else { + switch (fftLen) { + case 16: + case 64: + case 256: + case 1024: + case 4096: + _arm_radix4_butterfly_q15_mve(S, pSrc, fftLen); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_q15_mve(S, pSrc, fftLen); + break; + } + } + + + if (bitReverseFlag) + { + + arm_bitreversal_16_inpl_mve((uint16_t*)pSrc, S->bitRevLength, S->pBitRevTable); + + } +} + +#else + +#if !defined(ARM_MATH_NEON) + +extern void arm_radix4_butterfly_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef, + uint32_t twidCoefModifier); + +extern void arm_radix4_butterfly_inverse_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef, + uint32_t twidCoefModifier); + +extern void arm_bitreversal_16( + uint16_t * pSrc, + const uint16_t bitRevLen, + const uint16_t * pBitRevTable); + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef); + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_inverse_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef); + +#endif + +/** + @addtogroup ComplexFFTQ15 + @{ + */ + +/** + @brief Processing function for Q15 complex FFT. + @param[in] S points to an instance of Q15 CFFT structure + @param[in,out] p1 points to the complex data buffer. Processing occurs in-place + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + + @par Input and Output formats for CFFT Q15 + +| CFFT Size | Input Format | Output Format | Number of bits to upscale | +| ---------: | ------------: | -------------: | ------------------------: | +| 16 | 1.15 | 5.11 | 4 +| 64 | 1.15 | 7.9 | 6 +| 256 | 1.15 | 9.7 | 8 +| 1024 | 1.15 | 11.5 | 10 + + @par Input and Output formats for CIFFT Q15 + +| CIFFT Size | Input Format | Output Format | Number of bits to upscale | +| ----------: | ------------: | -------------: | ------------------------: | +| 16 | 1.15 | 5.11 | 0 +| 64 | 1.15 | 7.9 | 0 +| 256 | 1.15 | 9.7 | 0 +| 1024 | 1.15 | 11.5 | 0 + + @par Neon version + The neon version has a different API. + The input and output buffers must be + different. + There is a temporary buffer. + The bit reverse flag is not more + available in Neon version. + + @code + void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + const q15_t * src, + q15_t * dst, + q15_t *buffer, + uint8_t ifftFlag) + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + + */ + +#if defined(ARM_MATH_NEON) +#include "CMSIS_NE10_types.h" +#include "CMSIS_NE10_fft.h" + +ARM_DSP_ATTRIBUTE void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + const q15_t * src, + q15_t * dst, + q15_t *buffer, + uint8_t ifftFlag) +{ + arm_ne10_fft_c2c_1d_int16_neon (dst,src,S,ifftFlag,1,buffer); +} + +#else +ARM_DSP_ATTRIBUTE void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t L = S->fftLen; + + if (ifftFlag == 1U) + { + switch (L) + { + case 16: + case 64: + case 256: + case 1024: + case 4096: + arm_radix4_butterfly_inverse_q15 ( p1, L, (q15_t*)S->pTwiddle, 1 ); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_inverse_q15 ( p1, L, S->pTwiddle ); + break; + } + } + else + { + switch (L) + { + case 16: + case 64: + case 256: + case 1024: + case 4096: + arm_radix4_butterfly_q15 ( p1, L, (q15_t*)S->pTwiddle, 1 ); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_q15 ( p1, L, S->pTwiddle ); + break; + } + } + + if ( bitReverseFlag ) + arm_bitreversal_16 ((uint16_t*) p1, S->bitRevLength, S->pBitRevTable); +} + +#endif + +/** + @} end of ComplexFFTQ15 group + */ + +#if !defined(ARM_MATH_NEON) + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef) +{ + uint32_t i; + uint32_t n2; + q15_t p0, p1, p2, p3; +#if defined (ARM_MATH_DSP) + q31_t T, S, R; + q31_t coeff, out1, out2; + const q15_t *pC = pCoef; + q15_t *pSi = pSrc; + q15_t *pSl = pSrc + fftLen; +#else + uint32_t l; + q15_t xt, yt, cosVal, sinVal; +#endif + + n2 = fftLen >> 1U; + +#if defined (ARM_MATH_DSP) + + for (i = n2; i > 0; i--) + { + coeff = read_q15x2_ia (&pC); + + T = read_q15x2 (pSi); + T = __SHADD16(T, 0); /* this is just a SIMD arithmetic shift right by 1 */ + + S = read_q15x2 (pSl); + S = __SHADD16(S, 0); /* this is just a SIMD arithmetic shift right by 1 */ + + R = __QSUB16(T, S); + + write_q15x2_ia (&pSi, __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUAD(coeff, R) >> 16U; + out2 = __SMUSDX(coeff, R); +#else + out1 = __SMUSDX(R, coeff) >> 16U; + out2 = __SMUAD(coeff, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2_ia (&pSl, (q31_t)__PKHBT( out1, out2, 0 ) ); + } + +#else /* #if defined (ARM_MATH_DSP) */ + + for (i = 0; i < n2; i++) + { + cosVal = pCoef[2 * i]; + sinVal = pCoef[2 * i + 1]; + + l = i + n2; + + xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U); + pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U; + + yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U); + pSrc[2 * i + 1] = ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U; + + pSrc[2 * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16U)) + + ((int16_t) (((q31_t) yt * sinVal) >> 16U)) ); + + pSrc[2 * l + 1] = (((int16_t) (((q31_t) yt * cosVal) >> 16U)) - + ((int16_t) (((q31_t) xt * sinVal) >> 16U)) ); + } + +#endif /* #if defined (ARM_MATH_DSP) */ + + /* first col */ + arm_radix4_butterfly_q15( pSrc, n2, (q15_t*)pCoef, 2U); + + /* second col */ + arm_radix4_butterfly_q15( pSrc + fftLen, n2, (q15_t*)pCoef, 2U); + + n2 = fftLen >> 1U; + for (i = 0; i < n2; i++) + { + p0 = pSrc[4 * i + 0]; + p1 = pSrc[4 * i + 1]; + p2 = pSrc[4 * i + 2]; + p3 = pSrc[4 * i + 3]; + + p0 <<= 1U; + p1 <<= 1U; + p2 <<= 1U; + p3 <<= 1U; + + pSrc[4 * i + 0] = p0; + pSrc[4 * i + 1] = p1; + pSrc[4 * i + 2] = p2; + pSrc[4 * i + 3] = p3; + } + +} + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_inverse_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef) +{ + uint32_t i; + uint32_t n2; + q15_t p0, p1, p2, p3; +#if defined (ARM_MATH_DSP) + q31_t T, S, R; + q31_t coeff, out1, out2; + const q15_t *pC = pCoef; + q15_t *pSi = pSrc; + q15_t *pSl = pSrc + fftLen; +#else + uint32_t l; + q15_t xt, yt, cosVal, sinVal; +#endif + + n2 = fftLen >> 1U; + +#if defined (ARM_MATH_DSP) + + for (i = n2; i > 0; i--) + { + coeff = read_q15x2_ia (&pC); + + T = read_q15x2 (pSi); + T = __SHADD16(T, 0); /* this is just a SIMD arithmetic shift right by 1 */ + + S = read_q15x2 (pSl); + S = __SHADD16(S, 0); /* this is just a SIMD arithmetic shift right by 1 */ + + R = __QSUB16(T, S); + + write_q15x2_ia (&pSi, __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUSD(coeff, R) >> 16U; + out2 = __SMUADX(coeff, R); +#else + out1 = __SMUADX(R, coeff) >> 16U; + out2 = __SMUSD(__QSUB(0, coeff), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2_ia (&pSl, (q31_t)__PKHBT( out1, out2, 0 )); + } + +#else /* #if defined (ARM_MATH_DSP) */ + + for (i = 0; i < n2; i++) + { + cosVal = pCoef[2 * i]; + sinVal = pCoef[2 * i + 1]; + + l = i + n2; + + xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U); + pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U; + + yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U); + pSrc[2 * i + 1] = ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U; + + pSrc[2 * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16U)) - + ((int16_t) (((q31_t) yt * sinVal) >> 16U)) ); + + pSrc[2 * l + 1] = (((int16_t) (((q31_t) yt * cosVal) >> 16U)) + + ((int16_t) (((q31_t) xt * sinVal) >> 16U)) ); + } + +#endif /* #if defined (ARM_MATH_DSP) */ + + /* first col */ + arm_radix4_butterfly_inverse_q15( pSrc, n2, (q15_t*)pCoef, 2U); + + /* second col */ + arm_radix4_butterfly_inverse_q15( pSrc + fftLen, n2, (q15_t*)pCoef, 2U); + + n2 = fftLen >> 1U; + for (i = 0; i < n2; i++) + { + p0 = pSrc[4 * i + 0]; + p1 = pSrc[4 * i + 1]; + p2 = pSrc[4 * i + 2]; + p3 = pSrc[4 * i + 3]; + + p0 <<= 1U; + p1 <<= 1U; + p2 <<= 1U; + p3 <<= 1U; + + pSrc[4 * i + 0] = p0; + pSrc[4 * i + 1] = p1; + pSrc[4 * i + 2] = p2; + pSrc[4 * i + 3] = p3; + } +} +#endif /* defined NEON */ +#endif /* defined(ARM_MATH_MVEI) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_q31.c new file mode 100755 index 0000000..10bf8ef --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_q31.c @@ -0,0 +1,886 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_q31.c + * Description: Combined Radix Decimation in Frequency CFFT fixed point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + + + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_vec_fft.h" + + +static void _arm_radix4_butterfly_q31_mve( + const arm_cfft_instance_q31 * S, + q31_t *pSrc, + uint32_t fftLen) +{ + q31x4_t vecTmp0, vecTmp1; + q31x4_t vecSum0, vecDiff0, vecSum1, vecDiff1; + q31x4_t vecA, vecB, vecC, vecD; + uint32_t blkCnt; + uint32_t n1, n2; + uint32_t stage = 0; + int32_t iter = 1; + static const int32_t strides[4] = { + (0 - 16) * (int32_t)sizeof(q31_t *), (1 - 16) * (int32_t)sizeof(q31_t *), + (8 - 16) * (int32_t)sizeof(q31_t *), (9 - 16) * (int32_t)sizeof(q31_t *) + }; + + + /* + * Process first stages + * Each stage in middle stages provides two down scaling of the input + */ + n2 = fftLen; + n1 = n2; + n2 >>= 2u; + + for (int k = fftLen / 4u; k > 1; k >>= 2u) + { + q31_t const *p_rearranged_twiddle_tab_stride2 = + &S->rearranged_twiddle_stride2[ + S->rearranged_twiddle_tab_stride2_arr[stage]]; + q31_t const *p_rearranged_twiddle_tab_stride3 = &S->rearranged_twiddle_stride3[ + S->rearranged_twiddle_tab_stride3_arr[stage]]; + q31_t const *p_rearranged_twiddle_tab_stride1 = + &S->rearranged_twiddle_stride1[ + S->rearranged_twiddle_tab_stride1_arr[stage]]; + + q31_t * pBase = pSrc; + for (int i = 0; i < iter; i++) + { + q31_t *inA = pBase; + q31_t *inB = inA + n2 * CMPLX_DIM; + q31_t *inC = inB + n2 * CMPLX_DIM; + q31_t *inD = inC + n2 * CMPLX_DIM; + q31_t const *pW1 = p_rearranged_twiddle_tab_stride1; + q31_t const *pW2 = p_rearranged_twiddle_tab_stride2; + q31_t const *pW3 = p_rearranged_twiddle_tab_stride3; + q31x4_t vecW; + + + blkCnt = n2 / 2; + /* + * load 2 x q31 complex pair + */ + vecA = vldrwq_s32(inA); + vecC = vldrwq_s32(inC); + while (blkCnt > 0U) + { + vecB = vldrwq_s32(inB); + vecD = vldrwq_s32(inD); + + vecSum0 = vhaddq(vecA, vecC); + vecDiff0 = vhsubq(vecA, vecC); + + vecSum1 = vhaddq(vecB, vecD); + vecDiff1 = vhsubq(vecB, vecD); + /* + * [ 1 1 1 1 ] * [ A B C D ]' .* 1 + */ + vecTmp0 = vhaddq(vecSum0, vecSum1); + vst1q(inA, vecTmp0); + inA += 4; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]' + */ + vecTmp0 = vhsubq(vecSum0, vecSum1); + /* + * [ 1 -1 1 -1 ] * [ A B C D ]'.* W2 + */ + vecW = vld1q(pW2); + pW2 += 4; + vecTmp1 = MVE_CMPLX_MULT_FX_AxB(vecW, vecTmp0, q31x4_t); + + vst1q(inB, vecTmp1); + inB += 4; + /* + * [ 1 -i -1 +i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 -i -1 +i ] * [ A B C D ]'.* W1 + */ + vecW = vld1q(pW1); + pW1 += 4; + vecTmp1 = MVE_CMPLX_MULT_FX_AxB(vecW, vecTmp0, q31x4_t); + vst1q(inC, vecTmp1); + inC += 4; + /* + * [ 1 +i -1 -i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 +i -1 -i ] * [ A B C D ]'.* W3 + */ + vecW = vld1q(pW3); + pW3 += 4; + vecTmp1 = MVE_CMPLX_MULT_FX_AxB(vecW, vecTmp0, q31x4_t); + vst1q(inD, vecTmp1); + inD += 4; + + vecA = vldrwq_s32(inA); + vecC = vldrwq_s32(inC); + + blkCnt--; + } + pBase += CMPLX_DIM * n1; + } + n1 = n2; + n2 >>= 2u; + iter = iter << 2; + stage++; + } + + /* + * End of 1st stages process + * data is in 11.21(q21) format for the 1024 point as there are 3 middle stages + * data is in 9.23(q23) format for the 256 point as there are 2 middle stages + * data is in 7.25(q25) format for the 64 point as there are 1 middle stage + * data is in 5.27(q27) format for the 16 point as there are no middle stages + */ + + /* + * start of Last stage process + */ + uint32x4_t vecScGathAddr = vld1q_u32((uint32_t*)strides); + vecScGathAddr = vecScGathAddr + (uint32_t) pSrc; + + /* + * load scheduling + */ + vecA = vldrwq_gather_base_wb_s32(&vecScGathAddr, 64); + vecC = vldrwq_gather_base_s32(vecScGathAddr, 16); + + blkCnt = (fftLen >> 3); + while (blkCnt > 0U) + { + vecSum0 = vhaddq(vecA, vecC); + vecDiff0 = vhsubq(vecA, vecC); + + vecB = vldrwq_gather_base_s32(vecScGathAddr, 8); + vecD = vldrwq_gather_base_s32(vecScGathAddr, 24); + + vecSum1 = vhaddq(vecB, vecD); + vecDiff1 = vhsubq(vecB, vecD); + /* + * pre-load for next iteration + */ + vecA = vldrwq_gather_base_wb_s32(&vecScGathAddr, 64); + vecC = vldrwq_gather_base_s32(vecScGathAddr, 16); + + vecTmp0 = vhaddq(vecSum0, vecSum1); + vstrwq_scatter_base_s32(vecScGathAddr, -64, vecTmp0); + + vecTmp0 = vhsubq(vecSum0, vecSum1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 8, vecTmp0); + + vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 16, vecTmp0); + + vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 24, vecTmp0); + + blkCnt--; + } + + /* + * output is in 11.21(q21) format for the 1024 point + * output is in 9.23(q23) format for the 256 point + * output is in 7.25(q25) format for the 64 point + * output is in 5.27(q27) format for the 16 point + */ +} + + +static void arm_cfft_radix4by2_q31_mve(const arm_cfft_instance_q31 *S, q31_t *pSrc, uint32_t fftLen) +{ + uint32_t n2; + q31_t *pIn0; + q31_t *pIn1; + const q31_t *pCoef = S->pTwiddle; + uint32_t blkCnt; + q31x4_t vecIn0, vecIn1, vecSum, vecDiff; + q31x4_t vecCmplxTmp, vecTw; + + n2 = fftLen >> 1; + pIn0 = pSrc; + pIn1 = pSrc + fftLen; + + blkCnt = n2 / 2; + + while (blkCnt > 0U) + { + vecIn0 = vld1q_s32(pIn0); + vecIn1 = vld1q_s32(pIn1); + + vecIn0 = vecIn0 >> 1; + vecIn1 = vecIn1 >> 1; + vecSum = vhaddq(vecIn0, vecIn1); + vst1q(pIn0, vecSum); + pIn0 += 4; + + vecTw = vld1q_s32(pCoef); + pCoef += 4; + vecDiff = vhsubq(vecIn0, vecIn1); + + vecCmplxTmp = MVE_CMPLX_MULT_FX_AxConjB(vecDiff, vecTw, q31x4_t); + vst1q(pIn1, vecCmplxTmp); + pIn1 += 4; + + blkCnt--; + } + + _arm_radix4_butterfly_q31_mve(S, pSrc, n2); + + _arm_radix4_butterfly_q31_mve(S, pSrc + fftLen, n2); + + pIn0 = pSrc; + blkCnt = (fftLen << 1) >> 2; + while (blkCnt > 0U) + { + vecIn0 = vld1q_s32(pIn0); + vecIn0 = vecIn0 << 1; + vst1q(pIn0, vecIn0); + pIn0 += 4; + blkCnt--; + } + /* + * tail + * (will be merged thru tail predication) + */ + blkCnt = (fftLen << 1) & 3; + if (blkCnt > 0U) + { + mve_pred16_t p0 = vctp32q(blkCnt); + + vecIn0 = vld1q_s32(pIn0); + vecIn0 = vecIn0 << 1; + vstrwq_p(pIn0, vecIn0, p0); + } + +} + +static void _arm_radix4_butterfly_inverse_q31_mve( + const arm_cfft_instance_q31 *S, + q31_t *pSrc, + uint32_t fftLen) +{ + q31x4_t vecTmp0, vecTmp1; + q31x4_t vecSum0, vecDiff0, vecSum1, vecDiff1; + q31x4_t vecA, vecB, vecC, vecD; + uint32_t blkCnt; + uint32_t n1, n2; + uint32_t stage = 0; + int32_t iter = 1; + static const int32_t strides[4] = { + (0 - 16) * (int32_t)sizeof(q31_t *), (1 - 16) * (int32_t)sizeof(q31_t *), + (8 - 16) * (int32_t)sizeof(q31_t *), (9 - 16) * (int32_t)sizeof(q31_t *) + }; + + /* + * Process first stages + * Each stage in middle stages provides two down scaling of the input + */ + n2 = fftLen; + n1 = n2; + n2 >>= 2u; + + for (int k = fftLen / 4u; k > 1; k >>= 2u) + { + q31_t const *p_rearranged_twiddle_tab_stride2 = + &S->rearranged_twiddle_stride2[ + S->rearranged_twiddle_tab_stride2_arr[stage]]; + q31_t const *p_rearranged_twiddle_tab_stride3 = &S->rearranged_twiddle_stride3[ + S->rearranged_twiddle_tab_stride3_arr[stage]]; + q31_t const *p_rearranged_twiddle_tab_stride1 = + &S->rearranged_twiddle_stride1[ + S->rearranged_twiddle_tab_stride1_arr[stage]]; + + q31_t * pBase = pSrc; + for (int i = 0; i < iter; i++) + { + q31_t *inA = pBase; + q31_t *inB = inA + n2 * CMPLX_DIM; + q31_t *inC = inB + n2 * CMPLX_DIM; + q31_t *inD = inC + n2 * CMPLX_DIM; + q31_t const *pW1 = p_rearranged_twiddle_tab_stride1; + q31_t const *pW2 = p_rearranged_twiddle_tab_stride2; + q31_t const *pW3 = p_rearranged_twiddle_tab_stride3; + q31x4_t vecW; + + blkCnt = n2 / 2; + /* + * load 2 x q31 complex pair + */ + vecA = vldrwq_s32(inA); + vecC = vldrwq_s32(inC); + while (blkCnt > 0U) + { + vecB = vldrwq_s32(inB); + vecD = vldrwq_s32(inD); + + vecSum0 = vhaddq(vecA, vecC); + vecDiff0 = vhsubq(vecA, vecC); + + vecSum1 = vhaddq(vecB, vecD); + vecDiff1 = vhsubq(vecB, vecD); + /* + * [ 1 1 1 1 ] * [ A B C D ]' .* 1 + */ + vecTmp0 = vhaddq(vecSum0, vecSum1); + vst1q(inA, vecTmp0); + inA += 4; + /* + * [ 1 -1 1 -1 ] * [ A B C D ]' + */ + vecTmp0 = vhsubq(vecSum0, vecSum1); + /* + * [ 1 -1 1 -1 ] * [ A B C D ]'.* W2 + */ + vecW = vld1q(pW2); + pW2 += 4; + vecTmp1 = MVE_CMPLX_MULT_FX_AxConjB(vecTmp0, vecW, q31x4_t); + + vst1q(inB, vecTmp1); + inB += 4; + /* + * [ 1 -i -1 +i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 -i -1 +i ] * [ A B C D ]'.* W1 + */ + vecW = vld1q(pW1); + pW1 += 4; + vecTmp1 = MVE_CMPLX_MULT_FX_AxConjB(vecTmp0, vecW, q31x4_t); + vst1q(inC, vecTmp1); + inC += 4; + /* + * [ 1 +i -1 -i ] * [ A B C D ]' + */ + vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1); + /* + * [ 1 +i -1 -i ] * [ A B C D ]'.* W3 + */ + vecW = vld1q(pW3); + pW3 += 4; + vecTmp1 = MVE_CMPLX_MULT_FX_AxConjB(vecTmp0, vecW, q31x4_t); + vst1q(inD, vecTmp1); + inD += 4; + + vecA = vldrwq_s32(inA); + vecC = vldrwq_s32(inC); + + blkCnt--; + } + pBase += CMPLX_DIM * n1; + } + n1 = n2; + n2 >>= 2u; + iter = iter << 2; + stage++; + } + + /* + * End of 1st stages process + * data is in 11.21(q21) format for the 1024 point as there are 3 middle stages + * data is in 9.23(q23) format for the 256 point as there are 2 middle stages + * data is in 7.25(q25) format for the 64 point as there are 1 middle stage + * data is in 5.27(q27) format for the 16 point as there are no middle stages + */ + + /* + * start of Last stage process + */ + uint32x4_t vecScGathAddr = vld1q_u32((uint32_t*)strides); + vecScGathAddr = vecScGathAddr + (uint32_t) pSrc; + + /* + * load scheduling + */ + vecA = vldrwq_gather_base_wb_s32(&vecScGathAddr, 64); + vecC = vldrwq_gather_base_s32(vecScGathAddr, 16); + + blkCnt = (fftLen >> 3); + while (blkCnt > 0U) + { + vecSum0 = vhaddq(vecA, vecC); + vecDiff0 = vhsubq(vecA, vecC); + + vecB = vldrwq_gather_base_s32(vecScGathAddr, 8); + vecD = vldrwq_gather_base_s32(vecScGathAddr, 24); + + vecSum1 = vhaddq(vecB, vecD); + vecDiff1 = vhsubq(vecB, vecD); + /* + * pre-load for next iteration + */ + vecA = vldrwq_gather_base_wb_s32(&vecScGathAddr, 64); + vecC = vldrwq_gather_base_s32(vecScGathAddr, 16); + + vecTmp0 = vhaddq(vecSum0, vecSum1); + vstrwq_scatter_base_s32(vecScGathAddr, -64, vecTmp0); + + vecTmp0 = vhsubq(vecSum0, vecSum1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 8, vecTmp0); + + vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 16, vecTmp0); + + vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1); + vstrwq_scatter_base_s32(vecScGathAddr, -64 + 24, vecTmp0); + + blkCnt--; + } + /* + * output is in 11.21(q21) format for the 1024 point + * output is in 9.23(q23) format for the 256 point + * output is in 7.25(q25) format for the 64 point + * output is in 5.27(q27) format for the 16 point + */ +} + +static void arm_cfft_radix4by2_inverse_q31_mve(const arm_cfft_instance_q31 *S, q31_t *pSrc, uint32_t fftLen) +{ + uint32_t n2; + q31_t *pIn0; + q31_t *pIn1; + const q31_t *pCoef = S->pTwiddle; + + //uint16_t twidCoefModifier = arm_cfft_radix2_twiddle_factor(S->fftLen); + //q31_t twidIncr = (2 * twidCoefModifier * sizeof(q31_t)); + uint32_t blkCnt; + //uint64x2_t vecOffs; + q31x4_t vecIn0, vecIn1, vecSum, vecDiff; + q31x4_t vecCmplxTmp, vecTw; + + n2 = fftLen >> 1; + + pIn0 = pSrc; + pIn1 = pSrc + fftLen; + //vecOffs[0] = 0; + //vecOffs[1] = (uint64_t) twidIncr; + blkCnt = n2 / 2; + + while (blkCnt > 0U) + { + vecIn0 = vld1q_s32(pIn0); + vecIn1 = vld1q_s32(pIn1); + + vecIn0 = vecIn0 >> 1; + vecIn1 = vecIn1 >> 1; + vecSum = vhaddq(vecIn0, vecIn1); + vst1q(pIn0, vecSum); + pIn0 += 4; + + //vecTw = (q31x4_t) vldrdq_gather_offset_s64(pCoef, vecOffs); + vecTw = vld1q_s32(pCoef); + pCoef += 4; + vecDiff = vhsubq(vecIn0, vecIn1); + + vecCmplxTmp = MVE_CMPLX_MULT_FX_AxB(vecDiff, vecTw, q31x4_t); + vst1q(pIn1, vecCmplxTmp); + pIn1 += 4; + + //vecOffs = vaddq((q31x4_t) vecOffs, 2 * twidIncr); + blkCnt--; + } + + _arm_radix4_butterfly_inverse_q31_mve(S, pSrc, n2); + + _arm_radix4_butterfly_inverse_q31_mve(S, pSrc + fftLen, n2); + + pIn0 = pSrc; + blkCnt = (fftLen << 1) >> 2; + while (blkCnt > 0U) + { + vecIn0 = vld1q_s32(pIn0); + vecIn0 = vecIn0 << 1; + vst1q(pIn0, vecIn0); + pIn0 += 4; + blkCnt--; + } + /* + * tail + * (will be merged thru tail predication) + */ + blkCnt = (fftLen << 1) & 3; + if (blkCnt > 0U) + { + mve_pred16_t p0 = vctp32q(blkCnt); + + vecIn0 = vld1q_s32(pIn0); + vecIn0 = vecIn0 << 1; + vstrwq_p(pIn0, vecIn0, p0); + } + +} + + +ARM_DSP_ATTRIBUTE void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * pSrc, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t fftLen = S->fftLen; + + if (ifftFlag == 1U) { + + switch (fftLen) { + case 16: + case 64: + case 256: + case 1024: + case 4096: + _arm_radix4_butterfly_inverse_q31_mve(S, pSrc, fftLen); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_inverse_q31_mve(S, pSrc, fftLen); + break; + } + } else { + switch (fftLen) { + case 16: + case 64: + case 256: + case 1024: + case 4096: + _arm_radix4_butterfly_q31_mve(S, pSrc, fftLen); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_q31_mve(S, pSrc, fftLen); + break; + } + } + + + if (bitReverseFlag) + { + + arm_bitreversal_32_inpl_mve((uint32_t*)pSrc, S->bitRevLength, S->pBitRevTable); + + } +} +#else + +#if !defined(ARM_MATH_NEON) +extern void arm_radix4_butterfly_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint32_t twidCoefModifier); + +extern void arm_radix4_butterfly_inverse_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint32_t twidCoefModifier); + +extern void arm_bitreversal_32( + uint32_t * pSrc, + const uint16_t bitRevLen, + const uint16_t * pBitRevTable); + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef); + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_inverse_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef); +#endif + +/** + @addtogroup ComplexFFTQ31 + @{ + */ + +/** + @brief Processing function for the Q31 complex FFT. + @param[in] S points to an instance of the fixed-point CFFT structure + @param[in,out] p1 points to the complex data buffer. Processing occurs in-place + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + +@par Input and Output formats for CFFT Q31 + +| CFFT Size | Input Format | Output Format | Number of bits to upscale | +| ---------: | ------------: | -------------: | ------------------------: | +| 16 | 1.31 | 5.27 | 4 +| 64 | 1.31 | 7.25 | 6 +| 256 | 1.31 | 9.23 | 8 +| 1024 | 1.31 | 11.21 | 10 + +@par Input and Output formats for CIFFT Q31 + +| CIFFT Size | Input Format | Output Format | Number of bits to upscale | +| ----------: | ------------: | -------------: | ------------------------: | +| 16 | 1.31 | 5.27 | 0 +| 64 | 1.31 | 7.25 | 0 +| 256 | 1.31 | 9.23 | 0 +| 1024 | 1.31 | 11.21 | 0 + + + @par Neon version + The neon version has a different API. + The input and output buffers must be + different. + There is a temporary buffer. + The bit reverse flag is not more + available in Neon version. + + @code + void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + const q31_t * src, + q31_t * dst, + q31_t *buffer, + uint8_t ifftFlag + ) + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + + */ +#if defined(ARM_MATH_NEON) +#include "CMSIS_NE10_types.h" +#include "CMSIS_NE10_fft.h" + +ARM_DSP_ATTRIBUTE void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + const q31_t * src, + q31_t * dst, + q31_t *buffer, + uint8_t ifftFlag + ) +{ + arm_ne10_fft_c2c_1d_int32_neon (dst,src,S,ifftFlag,1,buffer); +} + +#else +ARM_DSP_ATTRIBUTE void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + uint32_t L = S->fftLen; + + if (ifftFlag == 1U) + { + switch (L) + { + case 16: + case 64: + case 256: + case 1024: + case 4096: + arm_radix4_butterfly_inverse_q31 ( p1, L, (q31_t*)S->pTwiddle, 1 ); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_inverse_q31 ( p1, L, S->pTwiddle ); + break; + } + } + else + { + switch (L) + { + case 16: + case 64: + case 256: + case 1024: + case 4096: + arm_radix4_butterfly_q31 ( p1, L, (q31_t*)S->pTwiddle, 1 ); + break; + + case 32: + case 128: + case 512: + case 2048: + arm_cfft_radix4by2_q31 ( p1, L, S->pTwiddle ); + break; + } + } + + if ( bitReverseFlag ) + arm_bitreversal_32 ((uint32_t*) p1, S->bitRevLength, S->pBitRevTable); +} +#endif + +/** + @} end of ComplexFFTQ31 group + */ + +#if !defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef) +{ + uint32_t i, l; + uint32_t n2; + q31_t xt, yt, cosVal, sinVal; + q31_t p0, p1; + + n2 = fftLen >> 1U; + for (i = 0; i < n2; i++) + { + cosVal = pCoef[2 * i]; + sinVal = pCoef[2 * i + 1]; + + l = i + n2; + + xt = (pSrc[2 * i] >> 2U) - (pSrc[2 * l] >> 2U); + pSrc[2 * i] = (pSrc[2 * i] >> 2U) + (pSrc[2 * l] >> 2U); + + yt = (pSrc[2 * i + 1] >> 2U) - (pSrc[2 * l + 1] >> 2U); + pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2U) + (pSrc[2 * i + 1] >> 2U); + + mult_32x32_keep32_R(p0, xt, cosVal); + mult_32x32_keep32_R(p1, yt, cosVal); + multAcc_32x32_keep32_R(p0, yt, sinVal); + multSub_32x32_keep32_R(p1, xt, sinVal); + + pSrc[2 * l] = p0 << 1; + pSrc[2 * l + 1] = p1 << 1; + } + + + /* first col */ + arm_radix4_butterfly_q31 (pSrc, n2, (q31_t*)pCoef, 2U); + + /* second col */ + arm_radix4_butterfly_q31 (pSrc + fftLen, n2, (q31_t*)pCoef, 2U); + + n2 = fftLen >> 1U; + for (i = 0; i < n2; i++) + { + p0 = pSrc[4 * i + 0]; + p1 = pSrc[4 * i + 1]; + xt = pSrc[4 * i + 2]; + yt = pSrc[4 * i + 3]; + + p0 <<= 1U; + p1 <<= 1U; + xt <<= 1U; + yt <<= 1U; + + pSrc[4 * i + 0] = p0; + pSrc[4 * i + 1] = p1; + pSrc[4 * i + 2] = xt; + pSrc[4 * i + 3] = yt; + } + +} + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_inverse_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef) +{ + uint32_t i, l; + uint32_t n2; + q31_t xt, yt, cosVal, sinVal; + q31_t p0, p1; + + n2 = fftLen >> 1U; + for (i = 0; i < n2; i++) + { + cosVal = pCoef[2 * i]; + sinVal = pCoef[2 * i + 1]; + + l = i + n2; + + xt = (pSrc[2 * i] >> 2U) - (pSrc[2 * l] >> 2U); + pSrc[2 * i] = (pSrc[2 * i] >> 2U) + (pSrc[2 * l] >> 2U); + + yt = (pSrc[2 * i + 1] >> 2U) - (pSrc[2 * l + 1] >> 2U); + pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2U) + (pSrc[2 * i + 1] >> 2U); + + mult_32x32_keep32_R(p0, xt, cosVal); + mult_32x32_keep32_R(p1, yt, cosVal); + multSub_32x32_keep32_R(p0, yt, sinVal); + multAcc_32x32_keep32_R(p1, xt, sinVal); + + pSrc[2 * l] = p0 << 1U; + pSrc[2 * l + 1] = p1 << 1U; + } + + /* first col */ + arm_radix4_butterfly_inverse_q31( pSrc, n2, (q31_t*)pCoef, 2U); + + /* second col */ + arm_radix4_butterfly_inverse_q31( pSrc + fftLen, n2, (q31_t*)pCoef, 2U); + + n2 = fftLen >> 1U; + for (i = 0; i < n2; i++) + { + p0 = pSrc[4 * i + 0]; + p1 = pSrc[4 * i + 1]; + xt = pSrc[4 * i + 2]; + yt = pSrc[4 * i + 3]; + + p0 <<= 1U; + p1 <<= 1U; + xt <<= 1U; + yt <<= 1U; + + pSrc[4 * i + 0] = p0; + pSrc[4 * i + 1] = p1; + pSrc[4 * i + 2] = xt; + pSrc[4 * i + 3] = yt; + } +} +#endif /* defined NEON */ +#endif /* defined(ARM_MATH_MVEI) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_f16.c new file mode 100755 index 0000000..23aa43c --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_f16.c @@ -0,0 +1,480 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix2_f16.c + * Description: Radix-2 Decimation in Frequency CFFT & CIFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" + +/** + * @defgroup ComplexFFTDeprecated Deprecated Complex FFT functions + */ + +#if defined(ARM_FLOAT16_SUPPORTED) + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_f16( + float16_t * pSrc, + uint32_t fftLen, + const float16_t * pCoef, + uint16_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_inverse_f16( + float16_t * pSrc, + uint32_t fftLen, + const float16_t * pCoef, + uint16_t twidCoefModifier, + float16_t onebyfftLen); + +extern void arm_bitreversal_f16( + float16_t * pSrc, + uint16_t fftSize, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + +/** + @ingroup ComplexFFT + */ + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Radix-2 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f16 and will be removed in the future + @param[in] S points to an instance of the floating-point Radix-2 CFFT/CIFFT structure + @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix2_f16( +const arm_cfft_radix2_instance_f16 * S, + float16_t * pSrc) +{ + + if (S->ifftFlag == 1U) + { + /* Complex IFFT radix-2 */ + arm_radix2_butterfly_inverse_f16(pSrc, S->fftLen, S->pTwiddle, + S->twidCoefModifier, S->onebyfftLen); + } + else + { + /* Complex FFT radix-2 */ + arm_radix2_butterfly_f16(pSrc, S->fftLen, S->pTwiddle, + S->twidCoefModifier); + } + + if (S->bitReverseFlag == 1U) + { + /* Bit Reversal */ + arm_bitreversal_f16(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); + } + +} + + +/** + @} end of ComplexFFTDeprecated group + */ + + + +/* ---------------------------------------------------------------------- +** Internal helper function used by the FFTs +** ------------------------------------------------------------------- */ + +/* +* @brief Core function for the floating-point CFFT butterfly process. +* @param[in, out] *pSrc points to the in-place buffer of floating-point data type. +* @param[in] fftLen length of the FFT. +* @param[in] *pCoef points to the twiddle coefficient buffer. +* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. +*/ + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_f16( +float16_t * pSrc, +uint32_t fftLen, +const float16_t * pCoef, +uint16_t twidCoefModifier) +{ + + uint32_t i, j, k, l; + uint32_t n1, n2, ia; + float16_t xt, yt, cosVal, sinVal; + float16_t p0, p1, p2, p3; + float16_t a0, a1; + +#if defined (ARM_MATH_DSP) + + /* Initializations for the first stage */ + n2 = fftLen >> 1; + ia = 0; + i = 0; + + // loop for groups + for (k = n2; k > 0; k--) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + + /* Twiddle coefficients index modifier */ + ia += twidCoefModifier; + + /* index calculation for the input as, */ + /* pSrc[i + 0], pSrc[i + fftLen/1] */ + l = i + n2; + + /* Butterfly implementation */ + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * l]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * l]; + + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * l + 1]; + a1 = (_Float16)pSrc[2 * l + 1] + (_Float16)pSrc[2 * i + 1]; + + p0 = (_Float16)xt * (_Float16)cosVal; + p1 = (_Float16)yt * (_Float16)sinVal; + p2 = (_Float16)yt * (_Float16)cosVal; + p3 = (_Float16)xt * (_Float16)sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = (_Float16)p0 + (_Float16)p1; + pSrc[2 * l + 1] = (_Float16)p2 - (_Float16)p3; + + i++; + } // groups loop end + + twidCoefModifier <<= 1U; + + // loop for stage + for (k = n2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + j = 0; + do + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia += twidCoefModifier; + + // loop for butterfly + i = j; + do + { + l = i + n2; + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * l]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * l]; + + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * l + 1]; + a1 = (_Float16)pSrc[2 * l + 1] + (_Float16)pSrc[2 * i + 1]; + + p0 = (_Float16)xt * (_Float16)cosVal; + p1 = (_Float16)yt * (_Float16)sinVal; + p2 = (_Float16)yt * (_Float16)cosVal; + p3 = (_Float16)xt * (_Float16)sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = (_Float16)p0 + (_Float16)p1; + pSrc[2 * l + 1] = (_Float16)p2 - (_Float16)p3; + + i += n1; + } while ( i < fftLen ); // butterfly loop end + j++; + } while ( j < n2); // groups loop end + twidCoefModifier <<= 1U; + } // stages loop end + + // loop for butterfly + for (i = 0; i < fftLen; i += 2) + { + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * i + 2]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * i + 2]; + + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * i + 3]; + a1 = (_Float16)pSrc[2 * i + 3] + (_Float16)pSrc[2 * i + 1]; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + pSrc[2 * i + 2] = xt; + pSrc[2 * i + 3] = yt; + } // groups loop end + +#else + + n2 = fftLen; + + // loop for stage + for (k = fftLen; k > 1; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + j = 0; + do + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia += twidCoefModifier; + + // loop for butterfly + i = j; + do + { + l = i + n2; + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * l]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * l]; + + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * l + 1]; + a1 = (_Float16)pSrc[2 * l + 1] + (_Float16)pSrc[2 * i + 1]; + + p0 = (_Float16)xt * (_Float16)cosVal; + p1 = (_Float16)yt * (_Float16)sinVal; + p2 = (_Float16)yt * (_Float16)cosVal; + p3 = (_Float16)xt * (_Float16)sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = (_Float16)p0 + (_Float16)p1; + pSrc[2 * l + 1] = (_Float16)p2 - (_Float16)p3; + + i += n1; + } while (i < fftLen); + j++; + } while (j < n2); + twidCoefModifier <<= 1U; + } + +#endif // #if defined (ARM_MATH_DSP) + +} + + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_inverse_f16( +float16_t * pSrc, +uint32_t fftLen, +const float16_t * pCoef, +uint16_t twidCoefModifier, +float16_t onebyfftLen) +{ + + uint32_t i, j, k, l; + uint32_t n1, n2, ia; + float16_t xt, yt, cosVal, sinVal; + float16_t p0, p1, p2, p3; + float16_t a0, a1; + +#if defined (ARM_MATH_DSP) + + n2 = fftLen >> 1; + ia = 0; + + // loop for groups + for (i = 0; i < n2; i++) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia += twidCoefModifier; + + l = i + n2; + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * l]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * l]; + + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * l + 1]; + a1 = (_Float16)pSrc[2 * l + 1] + (_Float16)pSrc[2 * i + 1]; + + p0 = (_Float16)xt * (_Float16)cosVal; + p1 = (_Float16)yt * (_Float16)sinVal; + p2 = (_Float16)yt * (_Float16)cosVal; + p3 = (_Float16)xt * (_Float16)sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = (_Float16)p0 - (_Float16)p1; + pSrc[2 * l + 1] = (_Float16)p2 + (_Float16)p3; + } // groups loop end + + twidCoefModifier <<= 1U; + + // loop for stage + for (k = fftLen / 2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + j = 0; + do + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia += twidCoefModifier; + + // loop for butterfly + i = j; + do + { + l = i + n2; + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * l]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * l]; + + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * l + 1]; + a1 = (_Float16)pSrc[2 * l + 1] + (_Float16)pSrc[2 * i + 1]; + + p0 = (_Float16)xt * (_Float16)cosVal; + p1 = (_Float16)yt * (_Float16)sinVal; + p2 = (_Float16)yt * (_Float16)cosVal; + p3 = (_Float16)xt * (_Float16)sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = (_Float16)p0 - (_Float16)p1; + pSrc[2 * l + 1] = (_Float16)p2 + (_Float16)p3; + + i += n1; + } while ( i < fftLen ); // butterfly loop end + j++; + } while (j < n2); // groups loop end + + twidCoefModifier <<= 1U; + } // stages loop end + + // loop for butterfly + for (i = 0; i < fftLen; i += 2) + { + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * i + 2]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * i + 2]; + + a1 = (_Float16)pSrc[2 * i + 3] + (_Float16)pSrc[2 * i + 1]; + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * i + 3]; + + p0 = (_Float16)a0 * (_Float16)onebyfftLen; + p2 = (_Float16)xt * (_Float16)onebyfftLen; + p1 = (_Float16)a1 * (_Float16)onebyfftLen; + p3 = (_Float16)yt * (_Float16)onebyfftLen; + + pSrc[2 * i] = p0; + pSrc[2 * i + 1] = p1; + pSrc[2 * i + 2] = p2; + pSrc[2 * i + 3] = p3; + } // butterfly loop end + +#else + + n2 = fftLen; + + // loop for stage + for (k = fftLen; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + j = 0; + do + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + // loop for butterfly + i = j; + do + { + l = i + n2; + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * l]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * l]; + + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * l + 1]; + a1 = (_Float16)pSrc[2 * l + 1] + (_Float16)pSrc[2 * i + 1]; + + p0 = (_Float16)xt * (_Float16)cosVal; + p1 = (_Float16)yt * (_Float16)sinVal; + p2 = (_Float16)yt * (_Float16)cosVal; + p3 = (_Float16)xt * (_Float16)sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = (_Float16)p0 - (_Float16)p1; + pSrc[2 * l + 1] = (_Float16)p2 + (_Float16)p3; + + i += n1; + } while ( i < fftLen ); // butterfly loop end + j++; + } while ( j < n2 ); // groups loop end + + twidCoefModifier = twidCoefModifier << 1U; + } // stages loop end + + n1 = n2; + n2 = n2 >> 1; + + // loop for butterfly + for (i = 0; i < fftLen; i += n1) + { + l = i + n2; + + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * l]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * l]; + + a1 = (_Float16)pSrc[2 * l + 1] + (_Float16)pSrc[2 * i + 1]; + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * l + 1]; + + p0 = (_Float16)a0 * (_Float16)onebyfftLen; + p2 = (_Float16)xt * (_Float16)onebyfftLen; + p1 = (_Float16)a1 * (_Float16)onebyfftLen; + p3 = (_Float16)yt * (_Float16)onebyfftLen; + + pSrc[2 * i] = p0; + pSrc[2U * l] = p2; + + pSrc[2 * i + 1] = p1; + pSrc[2U * l + 1U] = p3; + } // butterfly loop end + +#endif // #if defined (ARM_MATH_DSP) + +} + + +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_f32.c new file mode 100755 index 0000000..325d487 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_f32.c @@ -0,0 +1,470 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix2_f32.c + * Description: Radix-2 Decimation in Frequency CFFT & CIFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_f32( + float32_t * pSrc, + uint32_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_inverse_f32( + float32_t * pSrc, + uint32_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier, + float32_t onebyfftLen); + +extern void arm_bitreversal_f32( + float32_t * pSrc, + uint16_t fftSize, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Radix-2 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f32 and will be removed in the future + @param[in] S points to an instance of the floating-point Radix-2 CFFT/CIFFT structure + @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix2_f32( +const arm_cfft_radix2_instance_f32 * S, + float32_t * pSrc) +{ + + if (S->ifftFlag == 1U) + { + /* Complex IFFT radix-2 */ + arm_radix2_butterfly_inverse_f32(pSrc, S->fftLen, S->pTwiddle, + S->twidCoefModifier, S->onebyfftLen); + } + else + { + /* Complex FFT radix-2 */ + arm_radix2_butterfly_f32(pSrc, S->fftLen, S->pTwiddle, + S->twidCoefModifier); + } + + if (S->bitReverseFlag == 1U) + { + /* Bit Reversal */ + arm_bitreversal_f32(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); + } + +} + + +/** + @} end of ComplexFFTDeprecated group + */ + + + +/* ---------------------------------------------------------------------- + ** Internal helper function used by the FFTs + ** ------------------------------------------------------------------- */ + +/** + brief Core function for the floating-point CFFT butterfly process. + param[in,out] pSrc points to in-place buffer of floating-point data type + param[in] fftLen length of the FFT + param[in] pCoef points to twiddle coefficient buffer + param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table + return none + */ + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_f32( + float32_t * pSrc, + uint32_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier) +{ + + uint32_t i, j, k, l; + uint32_t n1, n2, ia; + float32_t xt, yt, cosVal, sinVal; + float32_t p0, p1, p2, p3; + float32_t a0, a1; + +#if defined (ARM_MATH_DSP) + + /* Initializations for the first stage */ + n2 = fftLen >> 1; + ia = 0; + i = 0; + + // loop for groups + for (k = n2; k > 0; k--) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + + /* Twiddle coefficients index modifier */ + ia += twidCoefModifier; + + /* index calculation for the input as, */ + /* pSrc[i + 0], pSrc[i + fftLen/1] */ + l = i + n2; + + /* Butterfly implementation */ + a0 = pSrc[2 * i] + pSrc[2 * l]; + xt = pSrc[2 * i] - pSrc[2 * l]; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1]; + + p0 = xt * cosVal; + p1 = yt * sinVal; + p2 = yt * cosVal; + p3 = xt * sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = p0 + p1; + pSrc[2 * l + 1] = p2 - p3; + + i++; + } // groups loop end + + twidCoefModifier <<= 1U; + + // loop for stage + for (k = n2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + j = 0; + do + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia += twidCoefModifier; + + // loop for butterfly + i = j; + do + { + l = i + n2; + a0 = pSrc[2 * i] + pSrc[2 * l]; + xt = pSrc[2 * i] - pSrc[2 * l]; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1]; + + p0 = xt * cosVal; + p1 = yt * sinVal; + p2 = yt * cosVal; + p3 = xt * sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = p0 + p1; + pSrc[2 * l + 1] = p2 - p3; + + i += n1; + } while ( i < fftLen ); // butterfly loop end + j++; + } while ( j < n2); // groups loop end + twidCoefModifier <<= 1U; + } // stages loop end + + // loop for butterfly + for (i = 0; i < fftLen; i += 2) + { + a0 = pSrc[2 * i] + pSrc[2 * i + 2]; + xt = pSrc[2 * i] - pSrc[2 * i + 2]; + + yt = pSrc[2 * i + 1] - pSrc[2 * i + 3]; + a1 = pSrc[2 * i + 3] + pSrc[2 * i + 1]; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + pSrc[2 * i + 2] = xt; + pSrc[2 * i + 3] = yt; + } // groups loop end + +#else /* #if defined (ARM_MATH_DSP) */ + + n2 = fftLen; + + // loop for stage + for (k = fftLen; k > 1; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + j = 0; + do + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia += twidCoefModifier; + + // loop for butterfly + i = j; + do + { + l = i + n2; + a0 = pSrc[2 * i] + pSrc[2 * l]; + xt = pSrc[2 * i] - pSrc[2 * l]; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1]; + + p0 = xt * cosVal; + p1 = yt * sinVal; + p2 = yt * cosVal; + p3 = xt * sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = p0 + p1; + pSrc[2 * l + 1] = p2 - p3; + + i += n1; + } while (i < fftLen); + j++; + } while (j < n2); + twidCoefModifier <<= 1U; + } + +#endif /* #if defined (ARM_MATH_DSP) */ + +} + + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_inverse_f32( + float32_t * pSrc, + uint32_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier, + float32_t onebyfftLen) +{ + + uint32_t i, j, k, l; + uint32_t n1, n2, ia; + float32_t xt, yt, cosVal, sinVal; + float32_t p0, p1, p2, p3; + float32_t a0, a1; + +#if defined (ARM_MATH_DSP) + + n2 = fftLen >> 1; + ia = 0; + + // loop for groups + for (i = 0; i < n2; i++) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia += twidCoefModifier; + + l = i + n2; + a0 = pSrc[2 * i] + pSrc[2 * l]; + xt = pSrc[2 * i] - pSrc[2 * l]; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1]; + + p0 = xt * cosVal; + p1 = yt * sinVal; + p2 = yt * cosVal; + p3 = xt * sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = p0 - p1; + pSrc[2 * l + 1] = p2 + p3; + } // groups loop end + + twidCoefModifier <<= 1U; + + // loop for stage + for (k = fftLen / 2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + j = 0; + do + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia += twidCoefModifier; + + // loop for butterfly + i = j; + do + { + l = i + n2; + a0 = pSrc[2 * i] + pSrc[2 * l]; + xt = pSrc[2 * i] - pSrc[2 * l]; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1]; + + p0 = xt * cosVal; + p1 = yt * sinVal; + p2 = yt * cosVal; + p3 = xt * sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = p0 - p1; + pSrc[2 * l + 1] = p2 + p3; + + i += n1; + } while ( i < fftLen ); // butterfly loop end + j++; + } while (j < n2); // groups loop end + + twidCoefModifier <<= 1U; + } // stages loop end + + // loop for butterfly + for (i = 0; i < fftLen; i += 2) + { + a0 = pSrc[2 * i] + pSrc[2 * i + 2]; + xt = pSrc[2 * i] - pSrc[2 * i + 2]; + + a1 = pSrc[2 * i + 3] + pSrc[2 * i + 1]; + yt = pSrc[2 * i + 1] - pSrc[2 * i + 3]; + + p0 = a0 * onebyfftLen; + p2 = xt * onebyfftLen; + p1 = a1 * onebyfftLen; + p3 = yt * onebyfftLen; + + pSrc[2 * i] = p0; + pSrc[2 * i + 1] = p1; + pSrc[2 * i + 2] = p2; + pSrc[2 * i + 3] = p3; + } // butterfly loop end + +#else /* #if defined (ARM_MATH_DSP) */ + + n2 = fftLen; + + // loop for stage + for (k = fftLen; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + j = 0; + do + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + // loop for butterfly + i = j; + do + { + l = i + n2; + a0 = pSrc[2 * i] + pSrc[2 * l]; + xt = pSrc[2 * i] - pSrc[2 * l]; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1]; + + p0 = xt * cosVal; + p1 = yt * sinVal; + p2 = yt * cosVal; + p3 = xt * sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = p0 - p1; + pSrc[2 * l + 1] = p2 + p3; + + i += n1; + } while ( i < fftLen ); // butterfly loop end + j++; + } while ( j < n2 ); // groups loop end + + twidCoefModifier = twidCoefModifier << 1U; + } // stages loop end + + n1 = n2; + n2 = n2 >> 1; + + // loop for butterfly + for (i = 0; i < fftLen; i += n1) + { + l = i + n2; + + a0 = pSrc[2 * i] + pSrc[2 * l]; + xt = pSrc[2 * i] - pSrc[2 * l]; + + a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1]; + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + + p0 = a0 * onebyfftLen; + p2 = xt * onebyfftLen; + p1 = a1 * onebyfftLen; + p3 = yt * onebyfftLen; + + pSrc[2 * i] = p0; + pSrc[2 * l] = p2; + + pSrc[2 * i + 1] = p1; + pSrc[2 * l + 1] = p3; + } // butterfly loop end + +#endif /* #if defined (ARM_MATH_DSP) */ + +} diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_f16.c new file mode 100755 index 0000000..03b0e3f --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_f16.c @@ -0,0 +1,207 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix2_init_f16.c + * Description: Radix-2 Decimation in Frequency Floating-point CFFT & CIFFT Initialization function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" +#include "arm_common_tables.h" +#include "arm_common_tables_f16.h" + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Initialization function for the floating-point CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f16 and will be removed in the future. + @param[in,out] S points to an instance of the floating-point CFFT/CIFFT structure + @param[in] fftLen length of the FFT + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Details + The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. +*/ + +#if defined(ARM_FLOAT16_SUPPORTED) + +ARM_DSP_ATTRIBUTE arm_status arm_cfft_radix2_init_f16( + arm_cfft_radix2_instance_f16 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + + /* Initialise the default arm status */ + status = ARM_MATH_SUCCESS; + + /* Initialise the FFT length */ + S->fftLen = fftLen; + + /* Initialise the Twiddle coefficient pointer */ + S->pTwiddle = (float16_t *) twiddleCoefF16_4096; + + /* Initialise the Flag for selection of CFFT or CIFFT */ + S->ifftFlag = ifftFlag; + + /* Initialise the Flag for calculation Bit reversal or not */ + S->bitReverseFlag = bitReverseFlag; + + + /* Initializations of structure parameters depending on the FFT length */ + switch (S->fftLen) + { + + case 4096U: + /* Initializations of structure parameters for 4096 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 1U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 1U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) armBitRevTable; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.000244140625; + break; + + case 2048U: + /* Initializations of structure parameters for 2048 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 2U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 2U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[1]; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.00048828125; + break; + + case 1024U: + /* Initializations of structure parameters for 1024 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 4U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 4U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.0009765625f; + break; + + case 512U: + /* Initializations of structure parameters for 512 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 8U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 8U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[7]; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.001953125; + break; + + case 256U: + /* Initializations of structure parameters for 256 point FFT */ + S->twidCoefModifier = 16U; + S->bitRevFactor = 16U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; + S->onebyfftLen = 0.00390625f; + break; + + case 128U: + /* Initializations of structure parameters for 128 point FFT */ + S->twidCoefModifier = 32U; + S->bitRevFactor = 32U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[31]; + S->onebyfftLen = 0.0078125; + break; + + case 64U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 64U; + S->bitRevFactor = 64U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; + S->onebyfftLen = 0.015625f; + break; + + case 32U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 128U; + S->bitRevFactor = 128U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[127]; + S->onebyfftLen = 0.03125; + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + S->twidCoefModifier = 256U; + S->bitRevFactor = 256U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; + S->onebyfftLen = 0.0625f; + break; + + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + + return (status); +} + +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ +/** + @} end of ComplexFFTDeprecated group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_f32.c new file mode 100755 index 0000000..409becb --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_f32.c @@ -0,0 +1,199 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix2_init_f32.c + * Description: Radix-2 Decimation in Frequency Floating-point CFFT & CIFFT Initialization function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Initialization function for the floating-point CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f32 and will be removed in the future. + @param[in,out] S points to an instance of the floating-point CFFT/CIFFT structure + @param[in] fftLen length of the FFT + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Details + The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. +*/ + +ARM_DSP_ATTRIBUTE arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialise the default arm status */ + status = ARM_MATH_SUCCESS; + + /* Initialise the FFT length */ + S->fftLen = fftLen; + + /* Initialise the Twiddle coefficient pointer */ + S->pTwiddle = (float32_t *) twiddleCoef; + + /* Initialise the Flag for selection of CFFT or CIFFT */ + S->ifftFlag = ifftFlag; + + /* Initialise the Flag for calculation Bit reversal or not */ + S->bitReverseFlag = bitReverseFlag; + + /* Initializations of structure parameters depending on the FFT length */ + switch (S->fftLen) + { + + case 4096U: + /* Initializations of structure parameters for 4096 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 1U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 1U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) armBitRevTable; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.000244140625; + break; + + case 2048U: + /* Initializations of structure parameters for 2048 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 2U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 2U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[1]; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.00048828125; + break; + + case 1024U: + /* Initializations of structure parameters for 1024 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 4U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 4U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.0009765625f; + break; + + case 512U: + /* Initializations of structure parameters for 512 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 8U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 8U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[7]; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.001953125; + break; + + case 256U: + /* Initializations of structure parameters for 256 point FFT */ + S->twidCoefModifier = 16U; + S->bitRevFactor = 16U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; + S->onebyfftLen = 0.00390625f; + break; + + case 128U: + /* Initializations of structure parameters for 128 point FFT */ + S->twidCoefModifier = 32U; + S->bitRevFactor = 32U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[31]; + S->onebyfftLen = 0.0078125; + break; + + case 64U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 64U; + S->bitRevFactor = 64U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; + S->onebyfftLen = 0.015625f; + break; + + case 32U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 128U; + S->bitRevFactor = 128U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[127]; + S->onebyfftLen = 0.03125; + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + S->twidCoefModifier = 256U; + S->bitRevFactor = 256U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; + S->onebyfftLen = 0.0625f; + break; + + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + return (status); +} + +/** + @} end of ComplexFFTDeprecated group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_q15.c new file mode 100755 index 0000000..3069239 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_q15.c @@ -0,0 +1,184 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix2_init_q15.c + * Description: Radix-2 Decimation in Frequency Q15 FFT & IFFT initialization function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Initialization function for the Q15 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q15 and will be removed + @param[in,out] S points to an instance of the Q15 CFFT/CIFFT structure. + @param[in] fftLen length of the FFT. + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Details + The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. +*/ + +ARM_DSP_ATTRIBUTE arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialise the default arm status */ + status = ARM_MATH_SUCCESS; + + /* Initialise the FFT length */ + S->fftLen = fftLen; + + /* Initialise the Twiddle coefficient pointer */ + S->pTwiddle = (q15_t *) twiddleCoef_4096_q15; + /* Initialise the Flag for selection of CFFT or CIFFT */ + S->ifftFlag = ifftFlag; + /* Initialise the Flag for calculation Bit reversal or not */ + S->bitReverseFlag = bitReverseFlag; + + /* Initializations of structure parameters depending on the FFT length */ + switch (S->fftLen) + { + case 4096U: + /* Initializations of structure parameters for 4096 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 1U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 1U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) armBitRevTable; + + break; + + case 2048U: + /* Initializations of structure parameters for 2048 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 2U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 2U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[1]; + + break; + + case 1024U: + /* Initializations of structure parameters for 1024 point FFT */ + S->twidCoefModifier = 4U; + S->bitRevFactor = 4U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; + + break; + + case 512U: + /* Initializations of structure parameters for 512 point FFT */ + S->twidCoefModifier = 8U; + S->bitRevFactor = 8U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[7]; + + break; + + case 256U: + /* Initializations of structure parameters for 256 point FFT */ + S->twidCoefModifier = 16U; + S->bitRevFactor = 16U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; + + break; + + case 128U: + /* Initializations of structure parameters for 128 point FFT */ + S->twidCoefModifier = 32U; + S->bitRevFactor = 32U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[31]; + + break; + + case 64U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 64U; + S->bitRevFactor = 64U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; + + break; + + case 32U: + /* Initializations of structure parameters for 32 point FFT */ + S->twidCoefModifier = 128U; + S->bitRevFactor = 128U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[127]; + + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + S->twidCoefModifier = 256U; + S->bitRevFactor = 256U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; + + break; + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + return (status); +} + +/** + @} end of ComplexFFTDeprecated group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_q31.c new file mode 100755 index 0000000..b3b1aa1 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_init_q31.c @@ -0,0 +1,181 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix2_init_q31.c + * Description: Radix-2 Decimation in Frequency Fixed-point CFFT & CIFFT Initialization function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Initialization function for the Q31 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed in the future. + @param[in,out] S points to an instance of the Q31 CFFT/CIFFT structure + @param[in] fftLen length of the FFT + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Details + The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. +*/ + +ARM_DSP_ATTRIBUTE arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialise the default arm status */ + status = ARM_MATH_SUCCESS; + + /* Initialise the FFT length */ + S->fftLen = fftLen; + + /* Initialise the Twiddle coefficient pointer */ + S->pTwiddle = (q31_t *) twiddleCoef_4096_q31; + + /* Initialise the Flag for selection of CFFT or CIFFT */ + S->ifftFlag = ifftFlag; + + /* Initialise the Flag for calculation Bit reversal or not */ + S->bitReverseFlag = bitReverseFlag; + + /* Initializations of Instance structure depending on the FFT length */ + switch (S->fftLen) + { + /* Initializations of structure parameters for 4096 point FFT */ + case 4096U: + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 1U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 1U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) armBitRevTable; + break; + + /* Initializations of structure parameters for 2048 point FFT */ + case 2048U: + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 2U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 2U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[1]; + break; + + /* Initializations of structure parameters for 1024 point FFT */ + case 1024U: + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 4U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 4U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; + break; + + /* Initializations of structure parameters for 512 point FFT */ + case 512U: + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 8U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 8U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[7]; + break; + + case 256U: + /* Initializations of structure parameters for 256 point FFT */ + S->twidCoefModifier = 16U; + S->bitRevFactor = 16U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; + break; + + case 128U: + /* Initializations of structure parameters for 128 point FFT */ + S->twidCoefModifier = 32U; + S->bitRevFactor = 32U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[31]; + break; + + case 64U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 64U; + S->bitRevFactor = 64U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; + break; + + case 32U: + /* Initializations of structure parameters for 32 point FFT */ + S->twidCoefModifier = 128U; + S->bitRevFactor = 128U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[127]; + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + S->twidCoefModifier = 256U; + S->bitRevFactor = 256U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; + break; + + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + return (status); +} + +/** + @} end of ComplexFFTDeprecated group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_q15.c new file mode 100755 index 0000000..0b2dd2f --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_q15.c @@ -0,0 +1,688 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix2_q15.c + * Description: Radix-2 Decimation in Frequency CFFT & CIFFT Fixed point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef, + uint16_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_inverse_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef, + uint16_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_bitreversal_q15( + q15_t * pSrc, + uint32_t fftLen, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Processing function for the fixed-point CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q15 and will be removed in the future. + @param[in] S points to an instance of the fixed-point CFFT/CIFFT structure + @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 * S, + q15_t * pSrc) +{ + + if (S->ifftFlag == 1U) + { + arm_radix2_butterfly_inverse_q15 (pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier); + } + else + { + arm_radix2_butterfly_q15 (pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier); + } + + arm_bitreversal_q15(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); +} + +/** + @} end of ComplexFFTDeprecated group + */ + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef, + uint16_t twidCoefModifier) +{ +#if defined (ARM_MATH_DSP) + + uint32_t i, j, k, l; + uint32_t n1, n2, ia; + q15_t in; + q31_t T, S, R; + q31_t coeff, out1, out2; + + //N = fftLen; + n2 = fftLen; + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + for (i = 0; i < n2; i++) + { + coeff = read_q15x2 ((q15_t *)pCoef + (ia * 2U)); + + ia = ia + twidCoefModifier; + + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + in = ((int16_t) (T & 0xFFFF)) >> 1; + T = ((T >> 1) & 0xFFFF0000) | (in & 0xFFFF); + + S = read_q15x2 (pSrc + (2 * l)); + in = ((int16_t) (S & 0xFFFF)) >> 1; + S = ((S >> 1) & 0xFFFF0000) | (in & 0xFFFF); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUAD(coeff, R) >> 16; + out2 = __SMUSDX(coeff, R); +#else + out1 = __SMUSDX(R, coeff) >> 16U; + out2 = __SMUAD(coeff, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2 (pSrc + (2U * l), (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF)); + + coeff = read_q15x2 ((q15_t *)pCoef + (ia * 2U)); + + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + i++; + l++; + + T = read_q15x2 (pSrc + (2 * i)); + in = ((int16_t) (T & 0xFFFF)) >> 1; + T = ((T >> 1) & 0xFFFF0000) | (in & 0xFFFF); + + S = read_q15x2 (pSrc + (2 * l)); + in = ((int16_t) (S & 0xFFFF)) >> 1; + S = ((S >> 1) & 0xFFFF0000) | (in & 0xFFFF); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUAD(coeff, R) >> 16; + out2 = __SMUSDX(coeff, R); +#else + + out1 = __SMUSDX(R, coeff) >> 16U; + out2 = __SMUAD(coeff, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2 (pSrc + (2U * l), (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF)); + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + + /* loop for stage */ + for (k = fftLen / 2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (j = 0; j < n2; j++) + { + coeff = read_q15x2 ((q15_t *)pCoef + (ia * 2U)); + + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + + S = read_q15x2 (pSrc + (2 * l)); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUAD(coeff, R) >> 16; + out2 = __SMUSDX(coeff, R); +#else + out1 = __SMUSDX(R, coeff) >> 16U; + out2 = __SMUAD(coeff, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2 (pSrc + (2U * l), (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF)); + + i += n1; + + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + + S = read_q15x2 (pSrc + (2 * l)); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUAD(coeff, R) >> 16; + out2 = __SMUSDX(coeff, R); +#else + out1 = __SMUSDX(R, coeff) >> 16U; + out2 = __SMUAD(coeff, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2 (pSrc + (2U * l), (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF)); + + } /* butterfly loop end */ + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + } /* stages loop end */ + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + coeff = read_q15x2 ((q15_t *)pCoef + (ia * 2U)); + + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = 0; i < fftLen; i += n1) + { + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + + S = read_q15x2 (pSrc + (2 * l)); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __QADD16(T, S)); + + write_q15x2 (pSrc + (2 * l), R); + + i += n1; + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + + S = read_q15x2 (pSrc + (2 * l)); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __QADD16(T, S)); + + write_q15x2 (pSrc + (2 * l), R); + + } /* groups loop end */ + + +#else /* #if defined (ARM_MATH_DSP) */ + + uint32_t i, j, k, l; + uint32_t n1, n2, ia; + q15_t xt, yt, cosVal, sinVal; + + + // N = fftLen; + n2 = fftLen; + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (j = 0; j < n2; j++) + { + cosVal = pCoef[(ia * 2)]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U); + pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U; + + yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U); + pSrc[2 * i + 1] = ((pSrc[2 * l + 1] >> 1U) + + (pSrc[2 * i + 1] >> 1U) ) >> 1U; + + pSrc[2 * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) + + ((int16_t) (((q31_t) yt * sinVal) >> 16))); + + pSrc[2U * l + 1] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) - + ((int16_t) (((q31_t) xt * sinVal) >> 16))); + + } /* butterfly loop end */ + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + + /* loop for stage */ + for (k = fftLen / 2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (j = 0; j < n2; j++) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U; + + pSrc[2 * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) + + ((int16_t) (((q31_t) yt * sinVal) >> 16))); + + pSrc[2U * l + 1] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) - + ((int16_t) (((q31_t) xt * sinVal) >> 16))); + + } /* butterfly loop end */ + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + } /* stages loop end */ + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (j = 0; j < n2; j++) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); + + pSrc[2 * l] = xt; + + pSrc[2 * l + 1] = yt; + + } /* butterfly loop end */ + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + +#endif /* #if defined (ARM_MATH_DSP) */ + +} + + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_inverse_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pCoef, + uint16_t twidCoefModifier) +{ +#if defined (ARM_MATH_DSP) + + uint32_t i, j, k, l; + uint32_t n1, n2, ia; + q15_t in; + q31_t T, S, R; + q31_t coeff, out1, out2; + + // N = fftLen; + n2 = fftLen; + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (i = 0; i < n2; i++) + { + coeff = read_q15x2 ((q15_t *)pCoef + (ia * 2U)); + + ia = ia + twidCoefModifier; + + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + in = ((int16_t) (T & 0xFFFF)) >> 1; + T = ((T >> 1) & 0xFFFF0000) | (in & 0xFFFF); + + S = read_q15x2 (pSrc + (2 * l)); + in = ((int16_t) (S & 0xFFFF)) >> 1; + S = ((S >> 1) & 0xFFFF0000) | (in & 0xFFFF); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUSD(coeff, R) >> 16; + out2 = __SMUADX(coeff, R); +#else + out1 = __SMUADX(R, coeff) >> 16U; + out2 = __SMUSD(__QSUB(0, coeff), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2 (pSrc + (2 * l), (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF)); + + coeff = read_q15x2 ((q15_t *)pCoef + (ia * 2U)); + + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + i++; + l++; + + T = read_q15x2 (pSrc + (2 * i)); + in = ((int16_t) (T & 0xFFFF)) >> 1; + T = ((T >> 1) & 0xFFFF0000) | (in & 0xFFFF); + + S = read_q15x2 (pSrc + (2 * l)); + in = ((int16_t) (S & 0xFFFF)) >> 1; + S = ((S >> 1) & 0xFFFF0000) | (in & 0xFFFF); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUSD(coeff, R) >> 16; + out2 = __SMUADX(coeff, R); +#else + out1 = __SMUADX(R, coeff) >> 16U; + out2 = __SMUSD(__QSUB(0, coeff), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2 (pSrc + (2 * l), (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF)); + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + + /* loop for stage */ + for (k = fftLen / 2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (j = 0; j < n2; j++) + { + coeff = read_q15x2 ((q15_t *)pCoef + (ia * 2U)); + + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + + S = read_q15x2 (pSrc + (2 * l)); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUSD(coeff, R) >> 16; + out2 = __SMUADX(coeff, R); +#else + out1 = __SMUADX(R, coeff) >> 16U; + out2 = __SMUSD(__QSUB(0, coeff), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2 (pSrc + (2 * l), (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF)); + + i += n1; + + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + + S = read_q15x2 (pSrc + (2 * l)); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __SHADD16(T, S)); + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUSD(coeff, R) >> 16; + out2 = __SMUADX(coeff, R); +#else + out1 = __SMUADX(R, coeff) >> 16U; + out2 = __SMUSD(__QSUB(0, coeff), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + write_q15x2 (pSrc + (2 * l), (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF)); + + } /* butterfly loop end */ + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + } /* stages loop end */ + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (j = 0; j < n2; j++) + { + coeff = read_q15x2 ((q15_t *)pCoef + (ia * 2U)); + + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + + T = read_q15x2 (pSrc + (2 * i)); + + S = read_q15x2 (pSrc + (2 * l)); + + R = __QSUB16(T, S); + + write_q15x2 (pSrc + (2 * i), __QADD16(T, S)); + + write_q15x2 (pSrc + (2 * l), R); + + } /* butterfly loop end */ + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + +#else /* #if defined (ARM_MATH_DSP) */ + + uint32_t i, j, k, l; + uint32_t n1, n2, ia; + q15_t xt, yt, cosVal, sinVal; + + // N = fftLen; + n2 = fftLen; + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (j = 0; j < n2; j++) + { + cosVal = pCoef[(ia * 2)]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U); + pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U; + + yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U); + pSrc[2 * i + 1] = ((pSrc[2 * l + 1] >> 1U) + + (pSrc[2 * i + 1] >> 1U) ) >> 1U; + + pSrc[2 * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) - + ((int16_t) (((q31_t) yt * sinVal) >> 16))); + + pSrc[2 * l + 1] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) + + ((int16_t) (((q31_t) xt * sinVal) >> 16))); + + } /* butterfly loop end */ + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + + /* loop for stage */ + for (k = fftLen / 2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + /* loop for groups */ + for (j = 0; j < n2; j++) + { + cosVal = pCoef[(ia * 2)]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U; + + pSrc[2 * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) - + ((int16_t) (((q31_t) yt * sinVal) >> 16)) ); + + pSrc[2 * l + 1] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) + + ((int16_t) (((q31_t) xt * sinVal) >> 16)) ); + + } /* butterfly loop end */ + + } /* groups loop end */ + + twidCoefModifier = twidCoefModifier << 1U; + } /* stages loop end */ + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + cosVal = pCoef[(ia * 2)]; + sinVal = pCoef[(ia * 2) + 1]; + + ia = ia + twidCoefModifier; + + /* loop for butterfly */ + for (i = 0; i < fftLen; i += n1) + { + l = i + n2; + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); + + pSrc[2 * l] = xt; + + pSrc[2 * l + 1] = yt; + + } /* groups loop end */ + + +#endif /* #if defined (ARM_MATH_DSP) */ + +} diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_q31.c new file mode 100755 index 0000000..39eca83 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix2_q31.c @@ -0,0 +1,336 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix2_q31.c + * Description: Radix-2 Decimation in Frequency CFFT & CIFFT Fixed point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint16_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_inverse_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint16_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_bitreversal_q31( + q31_t * pSrc, + uint32_t fftLen, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Processing function for the fixed-point CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed in the future. + @param[in] S points to an instance of the fixed-point CFFT/CIFFT structure + @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 * S, + q31_t * pSrc) +{ + + if (S->ifftFlag == 1U) + { + arm_radix2_butterfly_inverse_q31(pSrc, S->fftLen, + S->pTwiddle, S->twidCoefModifier); + } + else + { + arm_radix2_butterfly_q31(pSrc, S->fftLen, + S->pTwiddle, S->twidCoefModifier); + } + + arm_bitreversal_q31(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); +} + +/** + @} end of ComplexFFTDeprecated group + */ + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint16_t twidCoefModifier) +{ + + unsigned i, j, k, l, m; + unsigned n1, n2, ia; + q31_t xt, yt, cosVal, sinVal; + q31_t p0, p1; + + //N = fftLen; + n2 = fftLen; + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + for (i = 0; i < n2; i++) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + l = i + n2; + xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U); + pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U; + + yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U); + pSrc[2 * i + 1] = + ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U; + + mult_32x32_keep32_R(p0, xt, cosVal); + mult_32x32_keep32_R(p1, yt, cosVal); + multAcc_32x32_keep32_R(p0, yt, sinVal); + multSub_32x32_keep32_R(p1, xt, sinVal); + + pSrc[2U * l] = p0; + pSrc[2U * l + 1U] = p1; + + } // groups loop end + + twidCoefModifier <<= 1U; + + // loop for stage + for (k = fftLen / 2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + for (j = 0; j < n2; j++) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + // loop for butterfly + i = j; + m = fftLen / n1; + do + { + l = i + n2; + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U; + + mult_32x32_keep32_R(p0, xt, cosVal); + mult_32x32_keep32_R(p1, yt, cosVal); + multAcc_32x32_keep32_R(p0, yt, sinVal); + multSub_32x32_keep32_R(p1, xt, sinVal); + + pSrc[2U * l] = p0; + pSrc[2U * l + 1U] = p1; + i += n1; + m--; + } while ( m > 0); // butterfly loop end + + } // groups loop end + + twidCoefModifier <<= 1U; + } // stages loop end + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + // loop for butterfly + for (i = 0; i < fftLen; i += n1) + { + l = i + n2; + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); + + pSrc[2U * l] = xt; + + pSrc[2U * l + 1U] = yt; + + i += n1; + l = i + n2; + + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); + + pSrc[2U * l] = xt; + + pSrc[2U * l + 1U] = yt; + + } // butterfly loop end + +} + + +ARM_DSP_ATTRIBUTE void arm_radix2_butterfly_inverse_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint16_t twidCoefModifier) +{ + + unsigned i, j, k, l; + unsigned n1, n2, ia; + q31_t xt, yt, cosVal, sinVal; + q31_t p0, p1; + + //N = fftLen; + n2 = fftLen; + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + for (i = 0; i < n2; i++) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + l = i + n2; + xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U); + pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U; + + yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U); + pSrc[2 * i + 1] = + ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U; + + mult_32x32_keep32_R(p0, xt, cosVal); + mult_32x32_keep32_R(p1, yt, cosVal); + multSub_32x32_keep32_R(p0, yt, sinVal); + multAcc_32x32_keep32_R(p1, xt, sinVal); + + pSrc[2U * l] = p0; + pSrc[2U * l + 1U] = p1; + } // groups loop end + + twidCoefModifier = twidCoefModifier << 1U; + + // loop for stage + for (k = fftLen / 2; k > 2; k = k >> 1) + { + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + // loop for groups + for (j = 0; j < n2; j++) + { + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + // loop for butterfly + for (i = j; i < fftLen; i += n1) + { + l = i + n2; + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U; + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U; + + mult_32x32_keep32_R(p0, xt, cosVal); + mult_32x32_keep32_R(p1, yt, cosVal); + multSub_32x32_keep32_R(p0, yt, sinVal); + multAcc_32x32_keep32_R(p1, xt, sinVal); + + pSrc[2U * l] = p0; + pSrc[2U * l + 1U] = p1; + } // butterfly loop end + + } // groups loop end + + twidCoefModifier = twidCoefModifier << 1U; + } // stages loop end + + n1 = n2; + n2 = n2 >> 1; + ia = 0; + + cosVal = pCoef[ia * 2]; + sinVal = pCoef[(ia * 2) + 1]; + ia = ia + twidCoefModifier; + + // loop for butterfly + for (i = 0; i < fftLen; i += n1) + { + l = i + n2; + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); + + pSrc[2U * l] = xt; + + pSrc[2U * l + 1U] = yt; + + i += n1; + l = i + n2; + + xt = pSrc[2 * i] - pSrc[2 * l]; + pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]); + + yt = pSrc[2 * i + 1] - pSrc[2 * l + 1]; + pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]); + + pSrc[2U * l] = xt; + + pSrc[2U * l + 1U] = yt; + + } // butterfly loop end + +} diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_f16.c new file mode 100755 index 0000000..4096214 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_f16.c @@ -0,0 +1,1267 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix4_f16.c + * Description: Radix-4 Decimation in Frequency CFFT & CIFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" + +#if defined(ARM_FLOAT16_SUPPORTED) + +extern void arm_bitreversal_f16( + float16_t * pSrc, + uint16_t fftSize, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_f16( + float16_t * pSrc, + uint16_t fftLen, + const float16_t * pCoef, + uint16_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_inverse_f16( + float16_t * pSrc, + uint16_t fftLen, + const float16_t * pCoef, + uint16_t twidCoefModifier, + float16_t onebyfftLen); + + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_f16( + float16_t * pSrc, + uint32_t fftLen, + const float16_t * pCoef); + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/* +* @brief Core function for the floating-point CFFT butterfly process. +* @param[in, out] *pSrc points to the in-place buffer of floating-point data type. +* @param[in] fftLen length of the FFT. +* @param[in] *pCoef points to the twiddle coefficient buffer. +* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. +*/ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4by2_f16( + float16_t * pSrc, + uint32_t fftLen, + const float16_t * pCoef) +{ + uint32_t i, l; + uint32_t n2, ia; + float16_t xt, yt, cosVal, sinVal; + float16_t p0, p1,p2,p3,a0,a1; + + n2 = fftLen >> 1; + ia = 0; + for (i = 0; i < n2; i++) + { + cosVal = pCoef[2*ia]; + sinVal = pCoef[2*ia + 1]; + ia++; + + l = i + n2; + + /* Butterfly implementation */ + a0 = (_Float16)pSrc[2 * i] + (_Float16)pSrc[2 * l]; + xt = (_Float16)pSrc[2 * i] - (_Float16)pSrc[2 * l]; + + yt = (_Float16)pSrc[2 * i + 1] - (_Float16)pSrc[2 * l + 1]; + a1 = (_Float16)pSrc[2 * l + 1] + (_Float16)pSrc[2 * i + 1]; + + p0 = (_Float16)xt * (_Float16)cosVal; + p1 = (_Float16)yt * (_Float16)sinVal; + p2 = (_Float16)yt * (_Float16)cosVal; + p3 = (_Float16)xt * (_Float16)sinVal; + + pSrc[2 * i] = a0; + pSrc[2 * i + 1] = a1; + + pSrc[2 * l] = (_Float16)p0 + (_Float16)p1; + pSrc[2 * l + 1] = (_Float16)p2 - (_Float16)p3; + + } + + // first col + arm_radix4_butterfly_f16( pSrc, n2, (float16_t*)pCoef, 2U); + // second col + arm_radix4_butterfly_f16( pSrc + fftLen, n2, (float16_t*)pCoef, 2U); + +} + + +/** + @brief Processing function for the floating-point Radix-4 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f16 and will be removed in the future. + @param[in] S points to an instance of the floating-point Radix-4 CFFT/CIFFT structure + @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4_f16( + const arm_cfft_radix4_instance_f16 * S, + float16_t * pSrc) +{ + if (S->ifftFlag == 1U) + { + /* Complex IFFT radix-4 */ + arm_radix4_butterfly_inverse_f16(pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier, S->onebyfftLen); + } + else + { + /* Complex FFT radix-4 */ + arm_radix4_butterfly_f16(pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier); + } + + if (S->bitReverseFlag == 1U) + { + /* Bit Reversal */ + arm_bitreversal_f16(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); + } + +} + +/** + @} end of ComplexFFTDeprecated group + */ + +/* ---------------------------------------------------------------------- + * Internal helper function used by the FFTs + * ---------------------------------------------------------------------- */ + +/* +* @brief Core function for the floating-point CFFT butterfly process. +* @param[in, out] *pSrc points to the in-place buffer of floating-point data type. +* @param[in] fftLen length of the FFT. +* @param[in] *pCoef points to the twiddle coefficient buffer. +* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. +*/ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_f16( +float16_t * pSrc, +uint16_t fftLen, +const float16_t * pCoef, +uint16_t twidCoefModifier) +{ + + _Float16 co1, co2, co3, si1, si2, si3; + uint32_t ia1, ia2, ia3; + uint32_t i0, i1, i2, i3; + uint32_t n1, n2, j, k; + +#if defined (ARM_MATH_DSP) + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + + _Float16 xaIn, yaIn, xbIn, ybIn, xcIn, ycIn, xdIn, ydIn; + _Float16 Xaplusc, Xbplusd, Yaplusc, Ybplusd, Xaminusc, Xbminusd, Yaminusc, + Ybminusd; + _Float16 Xb12C_out, Yb12C_out, Xc12C_out, Yc12C_out, Xd12C_out, Yd12C_out; + _Float16 Xb12_out, Yb12_out, Xc12_out, Yc12_out, Xd12_out, Yd12_out; + float16_t *ptr1; + _Float16 p0,p1,p2,p3,p4,p5; + _Float16 a0,a1,a2,a3,a4,a5,a6,a7; + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* n2 = fftLen/4 */ + n2 >>= 2U; + i0 = 0U; + ia1 = 0U; + + j = n2; + + /* Calculation of first stage */ + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + xaIn = pSrc[(2U * i0)]; + yaIn = pSrc[(2U * i0) + 1U]; + + xbIn = pSrc[(2U * i1)]; + ybIn = pSrc[(2U * i1) + 1U]; + + xcIn = pSrc[(2U * i2)]; + ycIn = pSrc[(2U * i2) + 1U]; + + xdIn = pSrc[(2U * i3)]; + ydIn = pSrc[(2U * i3) + 1U]; + + /* xa + xc */ + Xaplusc = (_Float16)xaIn + (_Float16)xcIn; + /* xb + xd */ + Xbplusd = (_Float16)xbIn + (_Float16)xdIn; + /* ya + yc */ + Yaplusc = (_Float16)yaIn + (_Float16)ycIn; + /* yb + yd */ + Ybplusd = (_Float16)ybIn + (_Float16)ydIn; + + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + + /* xa - xc */ + Xaminusc = (_Float16)xaIn - (_Float16)xcIn; + /* xb - xd */ + Xbminusd = (_Float16)xbIn - (_Float16)xdIn; + /* ya - yc */ + Yaminusc = (_Float16)yaIn - (_Float16)ycIn; + /* yb - yd */ + Ybminusd = (_Float16)ybIn - (_Float16)ydIn; + + /* xa' = xa + xb + xc + xd */ + pSrc[(2U * i0)] = (_Float16)Xaplusc + (_Float16)Xbplusd; + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (_Float16)Yaplusc + (_Float16)Ybplusd; + + /* (xa - xc) + (yb - yd) */ + Xb12C_out = ((_Float16)Xaminusc + (_Float16)Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yb12C_out = ((_Float16)Yaminusc - (_Float16)Xbminusd); + /* (xa + xc) - (xb + xd) */ + Xc12C_out = ((_Float16)Xaplusc - (_Float16)Xbplusd); + /* (ya + yc) - (yb + yd) */ + Yc12C_out = ((_Float16)Yaplusc - (_Float16)Ybplusd); + /* (xa - xc) - (yb - yd) */ + Xd12C_out = ((_Float16)Xaminusc - (_Float16)Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yd12C_out = ((_Float16)Xbminusd + (_Float16)Yaminusc); + + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + + /* index calculation for the coefficients */ + ia3 = ia2 + ia1; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + Xb12_out = (_Float16)Xb12C_out * (_Float16)co1; + Yb12_out = (_Float16)Yb12C_out * (_Float16)co1; + Xc12_out = (_Float16)Xc12C_out * (_Float16)co2; + Yc12_out = (_Float16)Yc12C_out * (_Float16)co2; + Xd12_out = (_Float16)Xd12C_out * (_Float16)co3; + Yd12_out = (_Float16)Yd12C_out * (_Float16)co3; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + //Xb12_out -= Yb12C_out * si1; + p0 = (_Float16)Yb12C_out * (_Float16)si1; + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + //Yb12_out += Xb12C_out * si1; + p1 = (_Float16)Xb12C_out * (_Float16)si1; + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + //Xc12_out -= Yc12C_out * si2; + p2 = (_Float16)Yc12C_out * (_Float16)si2; + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + //Yc12_out += Xc12C_out * si2; + p3 = (_Float16)Xc12C_out * (_Float16)si2; + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + //Xd12_out -= Yd12C_out * si3; + p4 = (_Float16)Yd12C_out * (_Float16)si3; + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + //Yd12_out += Xd12C_out * si3; + p5 = (_Float16)Xd12C_out * (_Float16)si3; + + Xb12_out += (_Float16)p0; + Yb12_out -= (_Float16)p1; + Xc12_out += (_Float16)p2; + Yc12_out -= (_Float16)p3; + Xd12_out += (_Float16)p4; + Yd12_out -= (_Float16)p5; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = Xc12_out; + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = Yc12_out; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = Xb12_out; + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = Yb12_out; + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = Xd12_out; + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = Yd12_out; + + /* Twiddle coefficients index modifier */ + ia1 += twidCoefModifier; + + /* Updating input index */ + i0++; + + } + while (--j); + + twidCoefModifier <<= 2U; + + /* Calculation of second stage to excluding last stage */ + for (k = fftLen >> 2U; k > 4U; k >>= 2U) + { + /* Initializations for the first stage */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* Calculation of first stage */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 += twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + xaIn = pSrc[(2U * i0)]; + yaIn = pSrc[(2U * i0) + 1U]; + + xbIn = pSrc[(2U * i1)]; + ybIn = pSrc[(2U * i1) + 1U]; + + xcIn = pSrc[(2U * i2)]; + ycIn = pSrc[(2U * i2) + 1U]; + + xdIn = pSrc[(2U * i3)]; + ydIn = pSrc[(2U * i3) + 1U]; + + /* xa - xc */ + Xaminusc = (_Float16)xaIn - (_Float16)xcIn; + /* (xb - xd) */ + Xbminusd = (_Float16)xbIn - (_Float16)xdIn; + /* ya - yc */ + Yaminusc = (_Float16)yaIn - (_Float16)ycIn; + /* (yb - yd) */ + Ybminusd = (_Float16)ybIn - (_Float16)ydIn; + + /* xa + xc */ + Xaplusc = (_Float16)xaIn + (_Float16)xcIn; + /* xb + xd */ + Xbplusd = (_Float16)xbIn + (_Float16)xdIn; + /* ya + yc */ + Yaplusc = (_Float16)yaIn + (_Float16)ycIn; + /* yb + yd */ + Ybplusd = (_Float16)ybIn + (_Float16)ydIn; + + /* (xa - xc) + (yb - yd) */ + Xb12C_out = ((_Float16)Xaminusc + (_Float16)Ybminusd); + /* (ya - yc) - (xb - xd) */ + Yb12C_out = ((_Float16)Yaminusc - (_Float16)Xbminusd); + /* xa + xc -(xb + xd) */ + Xc12C_out = ((_Float16)Xaplusc - (_Float16)Xbplusd); + /* (ya + yc) - (yb + yd) */ + Yc12C_out = ((_Float16)Yaplusc - (_Float16)Ybplusd); + /* (xa - xc) - (yb - yd) */ + Xd12C_out = ((_Float16)Xaminusc - (_Float16)Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yd12C_out = ((_Float16)Xbminusd + (_Float16)Yaminusc); + + pSrc[(2U * i0)] = (_Float16)Xaplusc + (_Float16)Xbplusd; + pSrc[(2U * i0) + 1U] = (_Float16)Yaplusc + (_Float16)Ybplusd; + + Xb12_out = (_Float16)Xb12C_out * (_Float16)co1; + Yb12_out = (_Float16)Yb12C_out * (_Float16)co1; + Xc12_out = (_Float16)Xc12C_out * (_Float16)co2; + Yc12_out = (_Float16)Yc12C_out * (_Float16)co2; + Xd12_out = (_Float16)Xd12C_out * (_Float16)co3; + Yd12_out = (_Float16)Yd12C_out * (_Float16)co3; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + //Xb12_out -= Yb12C_out * si1; + p0 = (_Float16)Yb12C_out * (_Float16)si1; + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + //Yb12_out += Xb12C_out * si1; + p1 = (_Float16)Xb12C_out * (_Float16)si1; + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + //Xc12_out -= Yc12C_out * si2; + p2 = (_Float16)Yc12C_out * (_Float16)si2; + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + //Yc12_out += Xc12C_out * si2; + p3 = (_Float16)Xc12C_out * (_Float16)si2; + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + //Xd12_out -= Yd12C_out * si3; + p4 = (_Float16)Yd12C_out * (_Float16)si3; + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + //Yd12_out += Xd12C_out * si3; + p5 = (_Float16)Xd12C_out * (_Float16)si3; + + Xb12_out += (_Float16)p0; + Yb12_out -= (_Float16)p1; + Xc12_out += (_Float16)p2; + Yc12_out -= (_Float16)p3; + Xd12_out += (_Float16)p4; + Yd12_out -= (_Float16)p5; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = Xc12_out; + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = Yc12_out; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = Xb12_out; + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = Yb12_out; + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = Xd12_out; + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = Yd12_out; + + i0 += n1; + } while (i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } + + j = fftLen >> 2; + ptr1 = &pSrc[0]; + + /* Calculations of last stage */ + do + { + xaIn = ptr1[0]; + yaIn = ptr1[1]; + xbIn = ptr1[2]; + ybIn = ptr1[3]; + xcIn = ptr1[4]; + ycIn = ptr1[5]; + xdIn = ptr1[6]; + ydIn = ptr1[7]; + + /* xa + xc */ + Xaplusc = (_Float16)xaIn + (_Float16)xcIn; + + /* xa - xc */ + Xaminusc = (_Float16)xaIn - (_Float16)xcIn; + + /* ya + yc */ + Yaplusc = (_Float16)yaIn + (_Float16)ycIn; + + /* ya - yc */ + Yaminusc = (_Float16)yaIn - (_Float16)ycIn; + + /* xb + xd */ + Xbplusd = (_Float16)xbIn + (_Float16)xdIn; + + /* yb + yd */ + Ybplusd = (_Float16)ybIn + (_Float16)ydIn; + + /* (xb-xd) */ + Xbminusd = (_Float16)xbIn - (_Float16)xdIn; + + /* (yb-yd) */ + Ybminusd = (_Float16)ybIn - (_Float16)ydIn; + + /* xa' = xa + xb + xc + xd */ + a0 = ((_Float16)Xaplusc + (_Float16)Xbplusd); + /* ya' = ya + yb + yc + yd */ + a1 = ((_Float16)Yaplusc + (_Float16)Ybplusd); + /* xc' = (xa-xb+xc-xd) */ + a2 = ((_Float16)Xaplusc - (_Float16)Xbplusd); + /* yc' = (ya-yb+yc-yd) */ + a3 = ((_Float16)Yaplusc - (_Float16)Ybplusd); + /* xb' = (xa+yb-xc-yd) */ + a4 = ((_Float16)Xaminusc + (_Float16)Ybminusd); + /* yb' = (ya-xb-yc+xd) */ + a5 = ((_Float16)Yaminusc - (_Float16)Xbminusd); + /* xd' = (xa-yb-xc+yd)) */ + a6 = ((_Float16)Xaminusc - (_Float16)Ybminusd); + /* yd' = (ya+xb-yc-xd) */ + a7 = ((_Float16)Xbminusd + (_Float16)Yaminusc); + + ptr1[0] = a0; + ptr1[1] = a1; + ptr1[2] = a2; + ptr1[3] = a3; + ptr1[4] = a4; + ptr1[5] = a5; + ptr1[6] = a6; + ptr1[7] = a7; + + /* increment pointer by 8 */ + ptr1 += 8U; + } while (--j); + +#else + + _Float16 t1, t2, r1, r2, s1, s2; + + /* Run the below code for Cortex-M0 */ + + /* Initializations for the fft calculation */ + n2 = fftLen; + n1 = n2; + for (k = fftLen; k > 1U; k >>= 2U) + { + /* Initializations for the fft calculation */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* FFT Calculation */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* xa + xc */ + r1 = (_Float16)pSrc[(2U * i0)] + (_Float16)pSrc[(2U * i2)]; + + /* xa - xc */ + r2 = (_Float16)pSrc[(2U * i0)] - (_Float16)pSrc[(2U * i2)]; + + /* ya + yc */ + s1 = (_Float16)pSrc[(2U * i0) + 1U] + (_Float16)pSrc[(2U * i2) + 1U]; + + /* ya - yc */ + s2 = (_Float16)pSrc[(2U * i0) + 1U] - (_Float16)pSrc[(2U * i2) + 1U]; + + /* xb + xd */ + t1 = (_Float16)pSrc[2U * i1] + (_Float16)pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = (_Float16)r1 + (_Float16)t1; + + /* xa + xc -(xb + xd) */ + r1 = (_Float16)r1 - (_Float16)t1; + + /* yb + yd */ + t2 = (_Float16)pSrc[(2U * i1) + 1U] + (_Float16)pSrc[(2U * i3) + 1U]; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (_Float16)s1 + (_Float16)t2; + + /* (ya + yc) - (yb + yd) */ + s1 = (_Float16)s1 - (_Float16)t2; + + /* (yb - yd) */ + t1 = (_Float16)pSrc[(2U * i1) + 1U] - (_Float16)pSrc[(2U * i3) + 1U]; + + /* (xb - xd) */ + t2 = (_Float16)pSrc[2U * i1] - (_Float16)pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = ((_Float16)r1 * (_Float16)co2) + ((_Float16)s1 * (_Float16)si2); + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = ((_Float16)s1 * (_Float16)co2) - ((_Float16)r1 * (_Float16)si2); + + /* (xa - xc) + (yb - yd) */ + r1 = (_Float16)r2 + (_Float16)t1; + + /* (xa - xc) - (yb - yd) */ + r2 = (_Float16)r2 - (_Float16)t1; + + /* (ya - yc) - (xb - xd) */ + s1 = (_Float16)s2 - (_Float16)t2; + + /* (ya - yc) + (xb - xd) */ + s2 = (_Float16)s2 + (_Float16)t2; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = ((_Float16)r1 * (_Float16)co1) + ((_Float16)s1 * (_Float16)si1); + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = ((_Float16)s1 * (_Float16)co1) - ((_Float16)r1 * (_Float16)si1); + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = ((_Float16)r2 * (_Float16)co3) + ((_Float16)s2 * (_Float16)si3); + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = ((_Float16)s2 * (_Float16)co3) - ((_Float16)r2 * (_Float16)si3); + + i0 += n1; + } while ( i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } + +#endif /* #if defined (ARM_MATH_DSP) */ + +} + +/* +* @brief Core function for the floating-point CIFFT butterfly process. +* @param[in, out] *pSrc points to the in-place buffer of floating-point data type. +* @param[in] fftLen length of the FFT. +* @param[in] *pCoef points to twiddle coefficient buffer. +* @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. +* @param[in] onebyfftLen value of 1/fftLen. +*/ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_inverse_f16( +float16_t * pSrc, +uint16_t fftLen, +const float16_t * pCoef, +uint16_t twidCoefModifier, +float16_t onebyfftLen) +{ + _Float16 co1, co2, co3, si1, si2, si3; + uint32_t ia1, ia2, ia3; + uint32_t i0, i1, i2, i3; + uint32_t n1, n2, j, k; + +#if defined (ARM_MATH_DSP) + + _Float16 xaIn, yaIn, xbIn, ybIn, xcIn, ycIn, xdIn, ydIn; + _Float16 Xaplusc, Xbplusd, Yaplusc, Ybplusd, Xaminusc, Xbminusd, Yaminusc, + Ybminusd; + _Float16 Xb12C_out, Yb12C_out, Xc12C_out, Yc12C_out, Xd12C_out, Yd12C_out; + _Float16 Xb12_out, Yb12_out, Xc12_out, Yc12_out, Xd12_out, Yd12_out; + float16_t *ptr1; + _Float16 p0,p1,p2,p3,p4,p5,p6,p7; + _Float16 a0,a1,a2,a3,a4,a5,a6,a7; + + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* n2 = fftLen/4 */ + n2 >>= 2U; + i0 = 0U; + ia1 = 0U; + + j = n2; + + /* Calculation of first stage */ + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Butterfly implementation */ + xaIn = pSrc[(2U * i0)]; + yaIn = pSrc[(2U * i0) + 1U]; + + xcIn = pSrc[(2U * i2)]; + ycIn = pSrc[(2U * i2) + 1U]; + + xbIn = pSrc[(2U * i1)]; + ybIn = pSrc[(2U * i1) + 1U]; + + xdIn = pSrc[(2U * i3)]; + ydIn = pSrc[(2U * i3) + 1U]; + + /* xa + xc */ + Xaplusc = (_Float16)xaIn + (_Float16)xcIn; + /* xb + xd */ + Xbplusd = (_Float16)xbIn + (_Float16)xdIn; + /* ya + yc */ + Yaplusc = (_Float16)yaIn + (_Float16)ycIn; + /* yb + yd */ + Ybplusd = (_Float16)ybIn + (_Float16)ydIn; + + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + + /* xa - xc */ + Xaminusc = (_Float16)xaIn - (_Float16)xcIn; + /* xb - xd */ + Xbminusd = (_Float16)xbIn - (_Float16)xdIn; + /* ya - yc */ + Yaminusc = (_Float16)yaIn - (_Float16)ycIn; + /* yb - yd */ + Ybminusd = (_Float16)ybIn - (_Float16)ydIn; + + /* xa' = xa + xb + xc + xd */ + pSrc[(2U * i0)] = (_Float16)Xaplusc + (_Float16)Xbplusd; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (_Float16)Yaplusc + (_Float16)Ybplusd; + + /* (xa - xc) - (yb - yd) */ + Xb12C_out = ((_Float16)Xaminusc - (_Float16)Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yb12C_out = ((_Float16)Yaminusc + (_Float16)Xbminusd); + /* (xa + xc) - (xb + xd) */ + Xc12C_out = ((_Float16)Xaplusc - (_Float16)Xbplusd); + /* (ya + yc) - (yb + yd) */ + Yc12C_out = ((_Float16)Yaplusc - (_Float16)Ybplusd); + /* (xa - xc) + (yb - yd) */ + Xd12C_out = ((_Float16)Xaminusc + (_Float16)Ybminusd); + /* (ya - yc) - (xb - xd) */ + Yd12C_out = ((_Float16)Yaminusc - (_Float16)Xbminusd); + + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + + /* index calculation for the coefficients */ + ia3 = ia2 + ia1; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + Xb12_out = (_Float16)Xb12C_out * (_Float16)co1; + Yb12_out = (_Float16)Yb12C_out * (_Float16)co1; + Xc12_out = (_Float16)Xc12C_out * (_Float16)co2; + Yc12_out = (_Float16)Yc12C_out * (_Float16)co2; + Xd12_out = (_Float16)Xd12C_out * (_Float16)co3; + Yd12_out = (_Float16)Yd12C_out * (_Float16)co3; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + //Xb12_out -= Yb12C_out * si1; + p0 = (_Float16)Yb12C_out * (_Float16)si1; + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + //Yb12_out += Xb12C_out * si1; + p1 = (_Float16)Xb12C_out * (_Float16)si1; + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + //Xc12_out -= Yc12C_out * si2; + p2 = (_Float16)Yc12C_out * (_Float16)si2; + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + //Yc12_out += Xc12C_out * si2; + p3 = (_Float16)Xc12C_out * (_Float16)si2; + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + //Xd12_out -= Yd12C_out * si3; + p4 = (_Float16)Yd12C_out * (_Float16)si3; + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + //Yd12_out += Xd12C_out * si3; + p5 =(_Float16) Xd12C_out * (_Float16)si3; + + Xb12_out -= (_Float16)p0; + Yb12_out += (_Float16)p1; + Xc12_out -= (_Float16)p2; + Yc12_out += (_Float16)p3; + Xd12_out -= (_Float16)p4; + Yd12_out += (_Float16)p5; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = Xc12_out; + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = Yc12_out; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = Xb12_out; + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = Yb12_out; + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = Xd12_out; + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = Yd12_out; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + /* Updating input index */ + i0 = i0 + 1U; + + } while (--j); + + twidCoefModifier <<= 2U; + + /* Calculation of second stage to excluding last stage */ + for (k = fftLen >> 2U; k > 4U; k >>= 2U) + { + /* Initializations for the first stage */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* Calculation of first stage */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + xaIn = pSrc[(2U * i0)]; + yaIn = pSrc[(2U * i0) + 1U]; + + xbIn = pSrc[(2U * i1)]; + ybIn = pSrc[(2U * i1) + 1U]; + + xcIn = pSrc[(2U * i2)]; + ycIn = pSrc[(2U * i2) + 1U]; + + xdIn = pSrc[(2U * i3)]; + ydIn = pSrc[(2U * i3) + 1U]; + + /* xa - xc */ + Xaminusc = (_Float16)xaIn - (_Float16)xcIn; + /* (xb - xd) */ + Xbminusd = (_Float16)xbIn - (_Float16)xdIn; + /* ya - yc */ + Yaminusc = (_Float16)yaIn - (_Float16)ycIn; + /* (yb - yd) */ + Ybminusd = (_Float16)ybIn - (_Float16)ydIn; + + /* xa + xc */ + Xaplusc = (_Float16)xaIn + (_Float16)xcIn; + /* xb + xd */ + Xbplusd = (_Float16)xbIn + (_Float16)xdIn; + /* ya + yc */ + Yaplusc = (_Float16)yaIn + (_Float16)ycIn; + /* yb + yd */ + Ybplusd = (_Float16)ybIn + (_Float16)ydIn; + + /* (xa - xc) - (yb - yd) */ + Xb12C_out = ((_Float16)Xaminusc - (_Float16)Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yb12C_out = ((_Float16)Yaminusc + (_Float16)Xbminusd); + /* xa + xc -(xb + xd) */ + Xc12C_out = ((_Float16)Xaplusc - (_Float16)Xbplusd); + /* (ya + yc) - (yb + yd) */ + Yc12C_out = ((_Float16)Yaplusc - (_Float16)Ybplusd); + /* (xa - xc) + (yb - yd) */ + Xd12C_out = ((_Float16)Xaminusc + (_Float16)Ybminusd); + /* (ya - yc) - (xb - xd) */ + Yd12C_out = ((_Float16)Yaminusc - (_Float16)Xbminusd); + + pSrc[(2U * i0)] = (_Float16)Xaplusc + (_Float16)Xbplusd; + pSrc[(2U * i0) + 1U] = (_Float16)Yaplusc + (_Float16)Ybplusd; + + Xb12_out = (_Float16)Xb12C_out * (_Float16)co1; + Yb12_out = (_Float16)Yb12C_out * (_Float16)co1; + Xc12_out = (_Float16)Xc12C_out * (_Float16)co2; + Yc12_out = (_Float16)Yc12C_out * (_Float16)co2; + Xd12_out = (_Float16)Xd12C_out * (_Float16)co3; + Yd12_out = (_Float16)Yd12C_out * (_Float16)co3; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + //Xb12_out -= Yb12C_out * si1; + p0 = (_Float16)Yb12C_out * (_Float16)si1; + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + //Yb12_out += Xb12C_out * si1; + p1 = (_Float16)Xb12C_out * (_Float16)si1; + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + //Xc12_out -= Yc12C_out * si2; + p2 = (_Float16)Yc12C_out * (_Float16)si2; + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + //Yc12_out += Xc12C_out * si2; + p3 = (_Float16)Xc12C_out * (_Float16)si2; + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + //Xd12_out -= Yd12C_out * si3; + p4 = (_Float16)Yd12C_out * (_Float16)si3; + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + //Yd12_out += Xd12C_out * si3; + p5 = (_Float16)Xd12C_out * (_Float16)si3; + + Xb12_out -= (_Float16)p0; + Yb12_out += (_Float16)p1; + Xc12_out -= (_Float16)p2; + Yc12_out += (_Float16)p3; + Xd12_out -= (_Float16)p4; + Yd12_out += (_Float16)p5; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = Xc12_out; + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = Yc12_out; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = Xb12_out; + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = Yb12_out; + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = Xd12_out; + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = Yd12_out; + + i0 += n1; + } while (i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } + /* Initializations of last stage */ + + j = fftLen >> 2; + ptr1 = &pSrc[0]; + + /* Calculations of last stage */ + do + { + xaIn = ptr1[0]; + yaIn = ptr1[1]; + xbIn = ptr1[2]; + ybIn = ptr1[3]; + xcIn = ptr1[4]; + ycIn = ptr1[5]; + xdIn = ptr1[6]; + ydIn = ptr1[7]; + + /* Butterfly implementation */ + /* xa + xc */ + Xaplusc = (_Float16)xaIn + (_Float16)xcIn; + + /* xa - xc */ + Xaminusc = (_Float16)xaIn - (_Float16)xcIn; + + /* ya + yc */ + Yaplusc = (_Float16)yaIn + (_Float16)ycIn; + + /* ya - yc */ + Yaminusc = (_Float16)yaIn - (_Float16)ycIn; + + /* xb + xd */ + Xbplusd = (_Float16)xbIn + (_Float16)xdIn; + + /* yb + yd */ + Ybplusd = (_Float16)ybIn + (_Float16)ydIn; + + /* (xb-xd) */ + Xbminusd = (_Float16)xbIn - (_Float16)xdIn; + + /* (yb-yd) */ + Ybminusd = (_Float16)ybIn - (_Float16)ydIn; + + /* xa' = (xa+xb+xc+xd) * onebyfftLen */ + a0 = ((_Float16)Xaplusc + (_Float16)Xbplusd); + /* ya' = (ya+yb+yc+yd) * onebyfftLen */ + a1 = ((_Float16)Yaplusc + (_Float16)Ybplusd); + /* xc' = (xa-xb+xc-xd) * onebyfftLen */ + a2 = ((_Float16)Xaplusc - (_Float16)Xbplusd); + /* yc' = (ya-yb+yc-yd) * onebyfftLen */ + a3 = ((_Float16)Yaplusc - (_Float16)Ybplusd); + /* xb' = (xa-yb-xc+yd) * onebyfftLen */ + a4 = ((_Float16)Xaminusc - (_Float16)Ybminusd); + /* yb' = (ya+xb-yc-xd) * onebyfftLen */ + a5 = ((_Float16)Yaminusc + (_Float16)Xbminusd); + /* xd' = (xa-yb-xc+yd) * onebyfftLen */ + a6 = ((_Float16)Xaminusc + (_Float16)Ybminusd); + /* yd' = (ya-xb-yc+xd) * onebyfftLen */ + a7 = ((_Float16)Yaminusc - (_Float16)Xbminusd); + + p0 = (_Float16)a0 * (_Float16)onebyfftLen; + p1 = (_Float16)a1 * (_Float16)onebyfftLen; + p2 = (_Float16)a2 * (_Float16)onebyfftLen; + p3 = (_Float16)a3 * (_Float16)onebyfftLen; + p4 = (_Float16)a4 * (_Float16)onebyfftLen; + p5 = (_Float16)a5 * (_Float16)onebyfftLen; + p6 = (_Float16)a6 * (_Float16)onebyfftLen; + p7 = (_Float16)a7 * (_Float16)onebyfftLen; + + /* xa' = (xa+xb+xc+xd) * onebyfftLen */ + ptr1[0] = p0; + /* ya' = (ya+yb+yc+yd) * onebyfftLen */ + ptr1[1] = p1; + /* xc' = (xa-xb+xc-xd) * onebyfftLen */ + ptr1[2] = p2; + /* yc' = (ya-yb+yc-yd) * onebyfftLen */ + ptr1[3] = p3; + /* xb' = (xa-yb-xc+yd) * onebyfftLen */ + ptr1[4] = p4; + /* yb' = (ya+xb-yc-xd) * onebyfftLen */ + ptr1[5] = p5; + /* xd' = (xa-yb-xc+yd) * onebyfftLen */ + ptr1[6] = p6; + /* yd' = (ya-xb-yc+xd) * onebyfftLen */ + ptr1[7] = p7; + + /* increment source pointer by 8 for next calculations */ + ptr1 = ptr1 + 8U; + + } while (--j); + +#else + + float16_t t1, t2, r1, r2, s1, s2; + + /* Run the below code for Cortex-M0 */ + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* Calculation of first stage */ + for (k = fftLen; k > 4U; k >>= 2U) + { + /* Initializations for the first stage */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* Calculation of first stage */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* xa + xc */ + r1 = (_Float16)pSrc[(2U * i0)] + (_Float16)pSrc[(2U * i2)]; + + /* xa - xc */ + r2 = (_Float16)pSrc[(2U * i0)] - (_Float16)pSrc[(2U * i2)]; + + /* ya + yc */ + s1 = (_Float16)pSrc[(2U * i0) + 1U] + (_Float16)pSrc[(2U * i2) + 1U]; + + /* ya - yc */ + s2 = (_Float16)pSrc[(2U * i0) + 1U] - (_Float16)pSrc[(2U * i2) + 1U]; + + /* xb + xd */ + t1 = (_Float16)pSrc[2U * i1] + (_Float16)pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = (_Float16)r1 + (_Float16)t1; + + /* xa + xc -(xb + xd) */ + r1 = (_Float16)r1 - (_Float16)t1; + + /* yb + yd */ + t2 = (_Float16)pSrc[(2U * i1) + 1U] + (_Float16)pSrc[(2U * i3) + 1U]; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (_Float16)s1 + (_Float16)t2; + + /* (ya + yc) - (yb + yd) */ + s1 = (_Float16)s1 - (_Float16)t2; + + /* (yb - yd) */ + t1 = (_Float16)pSrc[(2U * i1) + 1U] - (_Float16)pSrc[(2U * i3) + 1U]; + + /* (xb - xd) */ + t2 = (_Float16)pSrc[2U * i1] - (_Float16)pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = ((_Float16)r1 * (_Float16)co2) - ((_Float16)s1 * (_Float16)si2); + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = ((_Float16)s1 * (_Float16)co2) + ((_Float16)r1 * (_Float16)si2); + + /* (xa - xc) - (yb - yd) */ + r1 = (_Float16)r2 - (_Float16)t1; + + /* (xa - xc) + (yb - yd) */ + r2 = (_Float16)r2 + (_Float16)t1; + + /* (ya - yc) + (xb - xd) */ + s1 = (_Float16)s2 + (_Float16)t2; + + /* (ya - yc) - (xb - xd) */ + s2 = (_Float16)s2 - (_Float16)t2; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = ((_Float16)r1 * (_Float16)co1) - ((_Float16)s1 * (_Float16)si1); + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = ((_Float16)s1 * (_Float16)co1) + ((_Float16)r1 * (_Float16)si1); + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = ((_Float16)r2 * (_Float16)co3) - ((_Float16)s2 * (_Float16)si3); + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = ((_Float16)s2 * (_Float16)co3) + ((_Float16)r2 * (_Float16)si3); + + i0 += n1; + } while ( i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } + /* Initializations of last stage */ + n1 = n2; + n2 >>= 2U; + + /* Calculations of last stage */ + for (i0 = 0U; i0 <= (fftLen - n1); i0 += n1) + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Butterfly implementation */ + /* xa + xc */ + r1 = (_Float16)pSrc[2U * i0] + (_Float16)pSrc[2U * i2]; + + /* xa - xc */ + r2 = (_Float16)pSrc[2U * i0] - (_Float16)pSrc[2U * i2]; + + /* ya + yc */ + s1 = (_Float16)pSrc[(2U * i0) + 1U] + (_Float16)pSrc[(2U * i2) + 1U]; + + /* ya - yc */ + s2 = (_Float16)pSrc[(2U * i0) + 1U] - (_Float16)pSrc[(2U * i2) + 1U]; + + /* xc + xd */ + t1 = (_Float16)pSrc[2U * i1] + (_Float16)pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = ((_Float16)r1 + (_Float16)t1) * (_Float16)onebyfftLen; + + /* (xa + xb) - (xc + xd) */ + r1 = (_Float16)r1 - (_Float16)t1; + + /* yb + yd */ + t2 = (_Float16)pSrc[(2U * i1) + 1U] + (_Float16)pSrc[(2U * i3) + 1U]; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = ((_Float16)s1 + (_Float16)t2) * (_Float16)onebyfftLen; + + /* (ya + yc) - (yb + yd) */ + s1 = (_Float16)s1 - (_Float16)t2; + + /* (yb-yd) */ + t1 = (_Float16)pSrc[(2U * i1) + 1U] - (_Float16)pSrc[(2U * i3) + 1U]; + + /* (xb-xd) */ + t2 = (_Float16)pSrc[2U * i1] - (_Float16)pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = (_Float16)r1 * (_Float16)onebyfftLen; + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = (_Float16)s1 * (_Float16)onebyfftLen; + + /* (xa - xc) - (yb-yd) */ + r1 = (_Float16)r2 - (_Float16)t1; + + /* (xa - xc) + (yb-yd) */ + r2 = (_Float16)r2 + (_Float16)t1; + + /* (ya - yc) + (xb-xd) */ + s1 = (_Float16)s2 + (_Float16)t2; + + /* (ya - yc) - (xb-xd) */ + s2 = (_Float16)s2 - (_Float16)t2; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = (_Float16)r1 * (_Float16)onebyfftLen; + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = (_Float16)s1 * (_Float16)onebyfftLen; + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = (_Float16)r2 * (_Float16)onebyfftLen; + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = (_Float16)s2 * (_Float16)onebyfftLen; + } + +#endif /* #if defined (ARM_MATH_DSP) */ +} + +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_f32.c new file mode 100755 index 0000000..536ce0f --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_f32.c @@ -0,0 +1,1201 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix4_f32.c + * Description: Radix-4 Decimation in Frequency CFFT & CIFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +extern void arm_bitreversal_f32( + float32_t * pSrc, + uint16_t fftSize, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_f32( + float32_t * pSrc, + uint16_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_inverse_f32( + float32_t * pSrc, + uint16_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier, + float32_t onebyfftLen); + + + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + + +/** + @brief Processing function for the floating-point Radix-4 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f32 and will be removed in the future. + @param[in] S points to an instance of the floating-point Radix-4 CFFT/CIFFT structure + @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 * S, + float32_t * pSrc) +{ + if (S->ifftFlag == 1U) + { + /* Complex IFFT radix-4 */ + arm_radix4_butterfly_inverse_f32(pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier, S->onebyfftLen); + } + else + { + /* Complex FFT radix-4 */ + arm_radix4_butterfly_f32(pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier); + } + + if (S->bitReverseFlag == 1U) + { + /* Bit Reversal */ + arm_bitreversal_f32(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); + } + +} + +/** + @} end of ComplexFFTDeprecated group + */ + +/* ---------------------------------------------------------------------- + * Internal helper function used by the FFTs + * ---------------------------------------------------------------------- */ + +/** + brief Core function for the floating-point CFFT butterfly process. + param[in,out] pSrc points to the in-place buffer of floating-point data type + param[in] fftLen length of the FFT + param[in] pCoef points to the twiddle coefficient buffer + param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table + return none + */ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_f32( + float32_t * pSrc, + uint16_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier) +{ + float32_t co1, co2, co3, si1, si2, si3; + uint32_t ia1, ia2, ia3; + uint32_t i0, i1, i2, i3; + uint32_t n1, n2, j, k; + +#if defined (ARM_MATH_LOOPUNROLL) + + float32_t xaIn, yaIn, xbIn, ybIn, xcIn, ycIn, xdIn, ydIn; + float32_t Xaplusc, Xbplusd, Yaplusc, Ybplusd, Xaminusc, Xbminusd, Yaminusc, + Ybminusd; + float32_t Xb12C_out, Yb12C_out, Xc12C_out, Yc12C_out, Xd12C_out, Yd12C_out; + float32_t Xb12_out, Yb12_out, Xc12_out, Yc12_out, Xd12_out, Yd12_out; + float32_t *ptr1; + float32_t p0,p1,p2,p3,p4,p5; + float32_t a0,a1,a2,a3,a4,a5,a6,a7; + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* n2 = fftLen/4 */ + n2 >>= 2U; + i0 = 0U; + ia1 = 0U; + + j = n2; + + /* Calculation of first stage */ + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + xaIn = pSrc[(2U * i0)]; + yaIn = pSrc[(2U * i0) + 1U]; + + xbIn = pSrc[(2U * i1)]; + ybIn = pSrc[(2U * i1) + 1U]; + + xcIn = pSrc[(2U * i2)]; + ycIn = pSrc[(2U * i2) + 1U]; + + xdIn = pSrc[(2U * i3)]; + ydIn = pSrc[(2U * i3) + 1U]; + + /* xa + xc */ + Xaplusc = xaIn + xcIn; + /* xb + xd */ + Xbplusd = xbIn + xdIn; + /* ya + yc */ + Yaplusc = yaIn + ycIn; + /* yb + yd */ + Ybplusd = ybIn + ydIn; + + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + + /* xa - xc */ + Xaminusc = xaIn - xcIn; + /* xb - xd */ + Xbminusd = xbIn - xdIn; + /* ya - yc */ + Yaminusc = yaIn - ycIn; + /* yb - yd */ + Ybminusd = ybIn - ydIn; + + /* xa' = xa + xb + xc + xd */ + pSrc[(2U * i0)] = Xaplusc + Xbplusd; + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = Yaplusc + Ybplusd; + + /* (xa - xc) + (yb - yd) */ + Xb12C_out = (Xaminusc + Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yb12C_out = (Yaminusc - Xbminusd); + /* (xa + xc) - (xb + xd) */ + Xc12C_out = (Xaplusc - Xbplusd); + /* (ya + yc) - (yb + yd) */ + Yc12C_out = (Yaplusc - Ybplusd); + /* (xa - xc) - (yb - yd) */ + Xd12C_out = (Xaminusc - Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yd12C_out = (Xbminusd + Yaminusc); + + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + + /* index calculation for the coefficients */ + ia3 = ia2 + ia1; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + Xb12_out = Xb12C_out * co1; + Yb12_out = Yb12C_out * co1; + Xc12_out = Xc12C_out * co2; + Yc12_out = Yc12C_out * co2; + Xd12_out = Xd12C_out * co3; + Yd12_out = Yd12C_out * co3; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + //Xb12_out -= Yb12C_out * si1; + p0 = Yb12C_out * si1; + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + //Yb12_out += Xb12C_out * si1; + p1 = Xb12C_out * si1; + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + //Xc12_out -= Yc12C_out * si2; + p2 = Yc12C_out * si2; + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + //Yc12_out += Xc12C_out * si2; + p3 = Xc12C_out * si2; + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + //Xd12_out -= Yd12C_out * si3; + p4 = Yd12C_out * si3; + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + //Yd12_out += Xd12C_out * si3; + p5 = Xd12C_out * si3; + + Xb12_out += p0; + Yb12_out -= p1; + Xc12_out += p2; + Yc12_out -= p3; + Xd12_out += p4; + Yd12_out -= p5; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = Xc12_out; + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = Yc12_out; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = Xb12_out; + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = Yb12_out; + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = Xd12_out; + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = Yd12_out; + + /* Twiddle coefficients index modifier */ + ia1 += twidCoefModifier; + + /* Updating input index */ + i0++; + + } + while (--j); + + twidCoefModifier <<= 2U; + + /* Calculation of second stage to excluding last stage */ + for (k = fftLen >> 2U; k > 4U; k >>= 2U) + { + /* Initializations for the first stage */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* Calculation of first stage */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[(ia1 * 2U)]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[(ia2 * 2U)]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[(ia3 * 2U)]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 += twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + xaIn = pSrc[(2U * i0)]; + yaIn = pSrc[(2U * i0) + 1U]; + + xbIn = pSrc[(2U * i1)]; + ybIn = pSrc[(2U * i1) + 1U]; + + xcIn = pSrc[(2U * i2)]; + ycIn = pSrc[(2U * i2) + 1U]; + + xdIn = pSrc[(2U * i3)]; + ydIn = pSrc[(2U * i3) + 1U]; + + /* xa - xc */ + Xaminusc = xaIn - xcIn; + /* (xb - xd) */ + Xbminusd = xbIn - xdIn; + /* ya - yc */ + Yaminusc = yaIn - ycIn; + /* (yb - yd) */ + Ybminusd = ybIn - ydIn; + + /* xa + xc */ + Xaplusc = xaIn + xcIn; + /* xb + xd */ + Xbplusd = xbIn + xdIn; + /* ya + yc */ + Yaplusc = yaIn + ycIn; + /* yb + yd */ + Ybplusd = ybIn + ydIn; + + /* (xa - xc) + (yb - yd) */ + Xb12C_out = (Xaminusc + Ybminusd); + /* (ya - yc) - (xb - xd) */ + Yb12C_out = (Yaminusc - Xbminusd); + /* xa + xc -(xb + xd) */ + Xc12C_out = (Xaplusc - Xbplusd); + /* (ya + yc) - (yb + yd) */ + Yc12C_out = (Yaplusc - Ybplusd); + /* (xa - xc) - (yb - yd) */ + Xd12C_out = (Xaminusc - Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yd12C_out = (Xbminusd + Yaminusc); + + pSrc[(2U * i0)] = Xaplusc + Xbplusd; + pSrc[(2U * i0) + 1U] = Yaplusc + Ybplusd; + + Xb12_out = Xb12C_out * co1; + Yb12_out = Yb12C_out * co1; + Xc12_out = Xc12C_out * co2; + Yc12_out = Yc12C_out * co2; + Xd12_out = Xd12C_out * co3; + Yd12_out = Yd12C_out * co3; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + //Xb12_out -= Yb12C_out * si1; + p0 = Yb12C_out * si1; + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + //Yb12_out += Xb12C_out * si1; + p1 = Xb12C_out * si1; + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + //Xc12_out -= Yc12C_out * si2; + p2 = Yc12C_out * si2; + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + //Yc12_out += Xc12C_out * si2; + p3 = Xc12C_out * si2; + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + //Xd12_out -= Yd12C_out * si3; + p4 = Yd12C_out * si3; + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + //Yd12_out += Xd12C_out * si3; + p5 = Xd12C_out * si3; + + Xb12_out += p0; + Yb12_out -= p1; + Xc12_out += p2; + Yc12_out -= p3; + Xd12_out += p4; + Yd12_out -= p5; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = Xc12_out; + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = Yc12_out; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = Xb12_out; + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = Yb12_out; + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = Xd12_out; + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = Yd12_out; + + i0 += n1; + } while (i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } + + j = fftLen >> 2; + ptr1 = &pSrc[0]; + + /* Calculations of last stage */ + do + { + xaIn = ptr1[0]; + yaIn = ptr1[1]; + xbIn = ptr1[2]; + ybIn = ptr1[3]; + xcIn = ptr1[4]; + ycIn = ptr1[5]; + xdIn = ptr1[6]; + ydIn = ptr1[7]; + + /* xa + xc */ + Xaplusc = xaIn + xcIn; + + /* xa - xc */ + Xaminusc = xaIn - xcIn; + + /* ya + yc */ + Yaplusc = yaIn + ycIn; + + /* ya - yc */ + Yaminusc = yaIn - ycIn; + + /* xb + xd */ + Xbplusd = xbIn + xdIn; + + /* yb + yd */ + Ybplusd = ybIn + ydIn; + + /* (xb-xd) */ + Xbminusd = xbIn - xdIn; + + /* (yb-yd) */ + Ybminusd = ybIn - ydIn; + + /* xa' = xa + xb + xc + xd */ + a0 = (Xaplusc + Xbplusd); + /* ya' = ya + yb + yc + yd */ + a1 = (Yaplusc + Ybplusd); + /* xc' = (xa-xb+xc-xd) */ + a2 = (Xaplusc - Xbplusd); + /* yc' = (ya-yb+yc-yd) */ + a3 = (Yaplusc - Ybplusd); + /* xb' = (xa+yb-xc-yd) */ + a4 = (Xaminusc + Ybminusd); + /* yb' = (ya-xb-yc+xd) */ + a5 = (Yaminusc - Xbminusd); + /* xd' = (xa-yb-xc+yd)) */ + a6 = (Xaminusc - Ybminusd); + /* yd' = (ya+xb-yc-xd) */ + a7 = (Xbminusd + Yaminusc); + + ptr1[0] = a0; + ptr1[1] = a1; + ptr1[2] = a2; + ptr1[3] = a3; + ptr1[4] = a4; + ptr1[5] = a5; + ptr1[6] = a6; + ptr1[7] = a7; + + /* increment pointer by 8 */ + ptr1 += 8U; + } while (--j); + +#else + + float32_t t1, t2, r1, r2, s1, s2; + + /* Initializations for the fft calculation */ + n2 = fftLen; + n1 = n2; + for (k = fftLen; k > 1U; k >>= 2U) + { + /* Initializations for the fft calculation */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* FFT Calculation */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* xa + xc */ + r1 = pSrc[(2U * i0)] + pSrc[(2U * i2)]; + + /* xa - xc */ + r2 = pSrc[(2U * i0)] - pSrc[(2U * i2)]; + + /* ya + yc */ + s1 = pSrc[(2U * i0) + 1U] + pSrc[(2U * i2) + 1U]; + + /* ya - yc */ + s2 = pSrc[(2U * i0) + 1U] - pSrc[(2U * i2) + 1U]; + + /* xb + xd */ + t1 = pSrc[2U * i1] + pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = r1 + t1; + + /* xa + xc -(xb + xd) */ + r1 = r1 - t1; + + /* yb + yd */ + t2 = pSrc[(2U * i1) + 1U] + pSrc[(2U * i3) + 1U]; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = s1 + t2; + + /* (ya + yc) - (yb + yd) */ + s1 = s1 - t2; + + /* (yb - yd) */ + t1 = pSrc[(2U * i1) + 1U] - pSrc[(2U * i3) + 1U]; + + /* (xb - xd) */ + t2 = pSrc[2U * i1] - pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = (r1 * co2) + (s1 * si2); + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = (s1 * co2) - (r1 * si2); + + /* (xa - xc) + (yb - yd) */ + r1 = r2 + t1; + + /* (xa - xc) - (yb - yd) */ + r2 = r2 - t1; + + /* (ya - yc) - (xb - xd) */ + s1 = s2 - t2; + + /* (ya - yc) + (xb - xd) */ + s2 = s2 + t2; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = (r1 * co1) + (s1 * si1); + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = (s1 * co1) - (r1 * si1); + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = (r2 * co3) + (s2 * si3); + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = (s2 * co3) - (r2 * si3); + + i0 += n1; + } while ( i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } + +#endif /* #if defined (ARM_MATH_LOOPUNROLL) */ + +} + +/** + brief Core function for the floating-point CIFFT butterfly process. + param[in,out] pSrc points to the in-place buffer of floating-point data type + param[in] fftLen length of the FFT + param[in] pCoef points to twiddle coefficient buffer + param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. + param[in] onebyfftLen value of 1/fftLen + return none + */ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_inverse_f32( + float32_t * pSrc, + uint16_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier, + float32_t onebyfftLen) +{ + float32_t co1, co2, co3, si1, si2, si3; + uint32_t ia1, ia2, ia3; + uint32_t i0, i1, i2, i3; + uint32_t n1, n2, j, k; + +#if defined (ARM_MATH_LOOPUNROLL) + + float32_t xaIn, yaIn, xbIn, ybIn, xcIn, ycIn, xdIn, ydIn; + float32_t Xaplusc, Xbplusd, Yaplusc, Ybplusd, Xaminusc, Xbminusd, Yaminusc, + Ybminusd; + float32_t Xb12C_out, Yb12C_out, Xc12C_out, Yc12C_out, Xd12C_out, Yd12C_out; + float32_t Xb12_out, Yb12_out, Xc12_out, Yc12_out, Xd12_out, Yd12_out; + float32_t *ptr1; + float32_t p0,p1,p2,p3,p4,p5,p6,p7; + float32_t a0,a1,a2,a3,a4,a5,a6,a7; + + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* n2 = fftLen/4 */ + n2 >>= 2U; + i0 = 0U; + ia1 = 0U; + + j = n2; + + /* Calculation of first stage */ + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Butterfly implementation */ + xaIn = pSrc[(2U * i0)]; + yaIn = pSrc[(2U * i0) + 1U]; + + xcIn = pSrc[(2U * i2)]; + ycIn = pSrc[(2U * i2) + 1U]; + + xbIn = pSrc[(2U * i1)]; + ybIn = pSrc[(2U * i1) + 1U]; + + xdIn = pSrc[(2U * i3)]; + ydIn = pSrc[(2U * i3) + 1U]; + + /* xa + xc */ + Xaplusc = xaIn + xcIn; + /* xb + xd */ + Xbplusd = xbIn + xdIn; + /* ya + yc */ + Yaplusc = yaIn + ycIn; + /* yb + yd */ + Ybplusd = ybIn + ydIn; + + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + + /* xa - xc */ + Xaminusc = xaIn - xcIn; + /* xb - xd */ + Xbminusd = xbIn - xdIn; + /* ya - yc */ + Yaminusc = yaIn - ycIn; + /* yb - yd */ + Ybminusd = ybIn - ydIn; + + /* xa' = xa + xb + xc + xd */ + pSrc[(2U * i0)] = Xaplusc + Xbplusd; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = Yaplusc + Ybplusd; + + /* (xa - xc) - (yb - yd) */ + Xb12C_out = (Xaminusc - Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yb12C_out = (Yaminusc + Xbminusd); + /* (xa + xc) - (xb + xd) */ + Xc12C_out = (Xaplusc - Xbplusd); + /* (ya + yc) - (yb + yd) */ + Yc12C_out = (Yaplusc - Ybplusd); + /* (xa - xc) + (yb - yd) */ + Xd12C_out = (Xaminusc + Ybminusd); + /* (ya - yc) - (xb - xd) */ + Yd12C_out = (Yaminusc - Xbminusd); + + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + + /* index calculation for the coefficients */ + ia3 = ia2 + ia1; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + Xb12_out = Xb12C_out * co1; + Yb12_out = Yb12C_out * co1; + Xc12_out = Xc12C_out * co2; + Yc12_out = Yc12C_out * co2; + Xd12_out = Xd12C_out * co3; + Yd12_out = Yd12C_out * co3; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + //Xb12_out -= Yb12C_out * si1; + p0 = Yb12C_out * si1; + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + //Yb12_out += Xb12C_out * si1; + p1 = Xb12C_out * si1; + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + //Xc12_out -= Yc12C_out * si2; + p2 = Yc12C_out * si2; + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + //Yc12_out += Xc12C_out * si2; + p3 = Xc12C_out * si2; + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + //Xd12_out -= Yd12C_out * si3; + p4 = Yd12C_out * si3; + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + //Yd12_out += Xd12C_out * si3; + p5 = Xd12C_out * si3; + + Xb12_out -= p0; + Yb12_out += p1; + Xc12_out -= p2; + Yc12_out += p3; + Xd12_out -= p4; + Yd12_out += p5; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = Xc12_out; + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = Yc12_out; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = Xb12_out; + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = Yb12_out; + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = Xd12_out; + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = Yd12_out; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + /* Updating input index */ + i0 = i0 + 1U; + + } while (--j); + + twidCoefModifier <<= 2U; + + /* Calculation of second stage to excluding last stage */ + for (k = fftLen >> 2U; k > 4U; k >>= 2U) + { + /* Initializations for the first stage */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* Calculation of first stage */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + xaIn = pSrc[(2U * i0)]; + yaIn = pSrc[(2U * i0) + 1U]; + + xbIn = pSrc[(2U * i1)]; + ybIn = pSrc[(2U * i1) + 1U]; + + xcIn = pSrc[(2U * i2)]; + ycIn = pSrc[(2U * i2) + 1U]; + + xdIn = pSrc[(2U * i3)]; + ydIn = pSrc[(2U * i3) + 1U]; + + /* xa - xc */ + Xaminusc = xaIn - xcIn; + /* (xb - xd) */ + Xbminusd = xbIn - xdIn; + /* ya - yc */ + Yaminusc = yaIn - ycIn; + /* (yb - yd) */ + Ybminusd = ybIn - ydIn; + + /* xa + xc */ + Xaplusc = xaIn + xcIn; + /* xb + xd */ + Xbplusd = xbIn + xdIn; + /* ya + yc */ + Yaplusc = yaIn + ycIn; + /* yb + yd */ + Ybplusd = ybIn + ydIn; + + /* (xa - xc) - (yb - yd) */ + Xb12C_out = (Xaminusc - Ybminusd); + /* (ya - yc) + (xb - xd) */ + Yb12C_out = (Yaminusc + Xbminusd); + /* xa + xc -(xb + xd) */ + Xc12C_out = (Xaplusc - Xbplusd); + /* (ya + yc) - (yb + yd) */ + Yc12C_out = (Yaplusc - Ybplusd); + /* (xa - xc) + (yb - yd) */ + Xd12C_out = (Xaminusc + Ybminusd); + /* (ya - yc) - (xb - xd) */ + Yd12C_out = (Yaminusc - Xbminusd); + + pSrc[(2U * i0)] = Xaplusc + Xbplusd; + pSrc[(2U * i0) + 1U] = Yaplusc + Ybplusd; + + Xb12_out = Xb12C_out * co1; + Yb12_out = Yb12C_out * co1; + Xc12_out = Xc12C_out * co2; + Yc12_out = Yc12C_out * co2; + Xd12_out = Xd12C_out * co3; + Yd12_out = Yd12C_out * co3; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + //Xb12_out -= Yb12C_out * si1; + p0 = Yb12C_out * si1; + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + //Yb12_out += Xb12C_out * si1; + p1 = Xb12C_out * si1; + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + //Xc12_out -= Yc12C_out * si2; + p2 = Yc12C_out * si2; + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + //Yc12_out += Xc12C_out * si2; + p3 = Xc12C_out * si2; + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + //Xd12_out -= Yd12C_out * si3; + p4 = Yd12C_out * si3; + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + //Yd12_out += Xd12C_out * si3; + p5 = Xd12C_out * si3; + + Xb12_out -= p0; + Yb12_out += p1; + Xc12_out -= p2; + Yc12_out += p3; + Xd12_out -= p4; + Yd12_out += p5; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = Xc12_out; + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = Yc12_out; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = Xb12_out; + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = Yb12_out; + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = Xd12_out; + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = Yd12_out; + + i0 += n1; + } while (i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } + /* Initializations of last stage */ + + j = fftLen >> 2; + ptr1 = &pSrc[0]; + + /* Calculations of last stage */ + do + { + xaIn = ptr1[0]; + yaIn = ptr1[1]; + xbIn = ptr1[2]; + ybIn = ptr1[3]; + xcIn = ptr1[4]; + ycIn = ptr1[5]; + xdIn = ptr1[6]; + ydIn = ptr1[7]; + + /* Butterfly implementation */ + /* xa + xc */ + Xaplusc = xaIn + xcIn; + + /* xa - xc */ + Xaminusc = xaIn - xcIn; + + /* ya + yc */ + Yaplusc = yaIn + ycIn; + + /* ya - yc */ + Yaminusc = yaIn - ycIn; + + /* xb + xd */ + Xbplusd = xbIn + xdIn; + + /* yb + yd */ + Ybplusd = ybIn + ydIn; + + /* (xb-xd) */ + Xbminusd = xbIn - xdIn; + + /* (yb-yd) */ + Ybminusd = ybIn - ydIn; + + /* xa' = (xa+xb+xc+xd) * onebyfftLen */ + a0 = (Xaplusc + Xbplusd); + /* ya' = (ya+yb+yc+yd) * onebyfftLen */ + a1 = (Yaplusc + Ybplusd); + /* xc' = (xa-xb+xc-xd) * onebyfftLen */ + a2 = (Xaplusc - Xbplusd); + /* yc' = (ya-yb+yc-yd) * onebyfftLen */ + a3 = (Yaplusc - Ybplusd); + /* xb' = (xa-yb-xc+yd) * onebyfftLen */ + a4 = (Xaminusc - Ybminusd); + /* yb' = (ya+xb-yc-xd) * onebyfftLen */ + a5 = (Yaminusc + Xbminusd); + /* xd' = (xa-yb-xc+yd) * onebyfftLen */ + a6 = (Xaminusc + Ybminusd); + /* yd' = (ya-xb-yc+xd) * onebyfftLen */ + a7 = (Yaminusc - Xbminusd); + + p0 = a0 * onebyfftLen; + p1 = a1 * onebyfftLen; + p2 = a2 * onebyfftLen; + p3 = a3 * onebyfftLen; + p4 = a4 * onebyfftLen; + p5 = a5 * onebyfftLen; + p6 = a6 * onebyfftLen; + p7 = a7 * onebyfftLen; + + /* xa' = (xa+xb+xc+xd) * onebyfftLen */ + ptr1[0] = p0; + /* ya' = (ya+yb+yc+yd) * onebyfftLen */ + ptr1[1] = p1; + /* xc' = (xa-xb+xc-xd) * onebyfftLen */ + ptr1[2] = p2; + /* yc' = (ya-yb+yc-yd) * onebyfftLen */ + ptr1[3] = p3; + /* xb' = (xa-yb-xc+yd) * onebyfftLen */ + ptr1[4] = p4; + /* yb' = (ya+xb-yc-xd) * onebyfftLen */ + ptr1[5] = p5; + /* xd' = (xa-yb-xc+yd) * onebyfftLen */ + ptr1[6] = p6; + /* yd' = (ya-xb-yc+xd) * onebyfftLen */ + ptr1[7] = p7; + + /* increment source pointer by 8 for next calculations */ + ptr1 = ptr1 + 8U; + + } while (--j); + +#else + + float32_t t1, t2, r1, r2, s1, s2; + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* Calculation of first stage */ + for (k = fftLen; k > 4U; k >>= 2U) + { + /* Initializations for the first stage */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* Calculation of first stage */ + j = 0; + do + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + i0 = j; + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* xa + xc */ + r1 = pSrc[(2U * i0)] + pSrc[(2U * i2)]; + + /* xa - xc */ + r2 = pSrc[(2U * i0)] - pSrc[(2U * i2)]; + + /* ya + yc */ + s1 = pSrc[(2U * i0) + 1U] + pSrc[(2U * i2) + 1U]; + + /* ya - yc */ + s2 = pSrc[(2U * i0) + 1U] - pSrc[(2U * i2) + 1U]; + + /* xb + xd */ + t1 = pSrc[2U * i1] + pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = r1 + t1; + + /* xa + xc -(xb + xd) */ + r1 = r1 - t1; + + /* yb + yd */ + t2 = pSrc[(2U * i1) + 1U] + pSrc[(2U * i3) + 1U]; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = s1 + t2; + + /* (ya + yc) - (yb + yd) */ + s1 = s1 - t2; + + /* (yb - yd) */ + t1 = pSrc[(2U * i1) + 1U] - pSrc[(2U * i3) + 1U]; + + /* (xb - xd) */ + t2 = pSrc[2U * i1] - pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = (r1 * co2) - (s1 * si2); + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = (s1 * co2) + (r1 * si2); + + /* (xa - xc) - (yb - yd) */ + r1 = r2 - t1; + + /* (xa - xc) + (yb - yd) */ + r2 = r2 + t1; + + /* (ya - yc) + (xb - xd) */ + s1 = s2 + t2; + + /* (ya - yc) - (xb - xd) */ + s2 = s2 - t2; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = (r1 * co1) - (s1 * si1); + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = (s1 * co1) + (r1 * si1); + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = (r2 * co3) - (s2 * si3); + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = (s2 * co3) + (r2 * si3); + + i0 += n1; + } while ( i0 < fftLen); + j++; + } while (j <= (n2 - 1U)); + twidCoefModifier <<= 2U; + } + /* Initializations of last stage */ + n1 = n2; + n2 >>= 2U; + + /* Calculations of last stage */ + for (i0 = 0U; i0 <= (fftLen - n1); i0 += n1) + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Butterfly implementation */ + /* xa + xc */ + r1 = pSrc[2U * i0] + pSrc[2U * i2]; + + /* xa - xc */ + r2 = pSrc[2U * i0] - pSrc[2U * i2]; + + /* ya + yc */ + s1 = pSrc[(2U * i0) + 1U] + pSrc[(2U * i2) + 1U]; + + /* ya - yc */ + s2 = pSrc[(2U * i0) + 1U] - pSrc[(2U * i2) + 1U]; + + /* xc + xd */ + t1 = pSrc[2U * i1] + pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = (r1 + t1) * onebyfftLen; + + /* (xa + xb) - (xc + xd) */ + r1 = r1 - t1; + + /* yb + yd */ + t2 = pSrc[(2U * i1) + 1U] + pSrc[(2U * i3) + 1U]; + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (s1 + t2) * onebyfftLen; + + /* (ya + yc) - (yb + yd) */ + s1 = s1 - t2; + + /* (yb-yd) */ + t1 = pSrc[(2U * i1) + 1U] - pSrc[(2U * i3) + 1U]; + + /* (xb-xd) */ + t2 = pSrc[2U * i1] - pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = r1 * onebyfftLen; + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = s1 * onebyfftLen; + + /* (xa - xc) - (yb-yd) */ + r1 = r2 - t1; + + /* (xa - xc) + (yb-yd) */ + r2 = r2 + t1; + + /* (ya - yc) + (xb-xd) */ + s1 = s2 + t2; + + /* (ya - yc) - (xb-xd) */ + s2 = s2 - t2; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = r1 * onebyfftLen; + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = s1 * onebyfftLen; + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = r2 * onebyfftLen; + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = s2 * onebyfftLen; + } + +#endif /* #if defined (ARM_MATH_LOOPUNROLL) */ +} + + diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_f16.c new file mode 100755 index 0000000..6c03dff --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_f16.c @@ -0,0 +1,162 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix4_init_f16.c + * Description: Radix-4 Decimation in Frequency Floating-point CFFT & CIFFT Initialization function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" +#include "arm_common_tables.h" +#include "arm_common_tables_f16.h" + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Initialization function for the floating-point CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f16 and will be removed in the future. + @param[in,out] S points to an instance of the floating-point CFFT/CIFFT structure + @param[in] fftLen length of the FFT + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Details + The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. + */ + +#if defined(ARM_FLOAT16_SUPPORTED) + +ARM_DSP_ATTRIBUTE arm_status arm_cfft_radix4_init_f16( + arm_cfft_radix4_instance_f16 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialise the default arm status */ + status = ARM_MATH_SUCCESS; + + /* Initialise the FFT length */ + S->fftLen = fftLen; + + /* Initialise the Twiddle coefficient pointer */ + S->pTwiddle = (float16_t *) twiddleCoefF16; + + /* Initialise the Flag for selection of CFFT or CIFFT */ + S->ifftFlag = ifftFlag; + + /* Initialise the Flag for calculation Bit reversal or not */ + S->bitReverseFlag = bitReverseFlag; + + /* Initializations of structure parameters depending on the FFT length */ + switch (S->fftLen) + { + + case 4096U: + /* Initializations of structure parameters for 4096 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 1U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 1U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) armBitRevTable; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.000244140625; + break; + + case 1024U: + /* Initializations of structure parameters for 1024 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 4U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 4U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.0009765625f; + break; + + + case 256U: + /* Initializations of structure parameters for 256 point FFT */ + S->twidCoefModifier = 16U; + S->bitRevFactor = 16U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; + S->onebyfftLen = 0.00390625f; + break; + + case 64U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 64U; + S->bitRevFactor = 64U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; + S->onebyfftLen = 0.015625f; + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + S->twidCoefModifier = 256U; + S->bitRevFactor = 256U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; + S->onebyfftLen = 0.0625f; + break; + + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + return (status); +} +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ +/** + @} end of ComplexFFTDeprecated group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_f32.c new file mode 100755 index 0000000..2fdae65 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_f32.c @@ -0,0 +1,160 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix4_init_f32.c + * Description: Radix-4 Decimation in Frequency Floating-point CFFT & CIFFT Initialization function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Initialization function for the floating-point CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f32 and will be removed in the future. + @param[in,out] S points to an instance of the floating-point CFFT/CIFFT structure + @param[in] fftLen length of the FFT + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Details + The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. + */ + +ARM_DSP_ATTRIBUTE arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialise the default arm status */ + status = ARM_MATH_SUCCESS; + + /* Initialise the FFT length */ + S->fftLen = fftLen; + + /* Initialise the Twiddle coefficient pointer */ + S->pTwiddle = (float32_t *) twiddleCoef; + + /* Initialise the Flag for selection of CFFT or CIFFT */ + S->ifftFlag = ifftFlag; + + /* Initialise the Flag for calculation Bit reversal or not */ + S->bitReverseFlag = bitReverseFlag; + + /* Initializations of structure parameters depending on the FFT length */ + switch (S->fftLen) + { + + case 4096U: + /* Initializations of structure parameters for 4096 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 1U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 1U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) armBitRevTable; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.000244140625; + break; + + case 1024U: + /* Initializations of structure parameters for 1024 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 4U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 4U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; + /* Initialise the 1/fftLen Value */ + S->onebyfftLen = 0.0009765625f; + break; + + + case 256U: + /* Initializations of structure parameters for 256 point FFT */ + S->twidCoefModifier = 16U; + S->bitRevFactor = 16U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; + S->onebyfftLen = 0.00390625f; + break; + + case 64U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 64U; + S->bitRevFactor = 64U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; + S->onebyfftLen = 0.015625f; + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + S->twidCoefModifier = 256U; + S->bitRevFactor = 256U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; + S->onebyfftLen = 0.0625f; + break; + + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + + return (status); +} + +/** + @} end of ComplexFFTDeprecated group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_q15.c new file mode 100755 index 0000000..04de4ce --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_q15.c @@ -0,0 +1,147 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix4_init_q15.c + * Description: Radix-4 Decimation in Frequency Q15 FFT & IFFT initialization function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + + +/** + @brief Initialization function for the Q15 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q15 and will be removed in the future. + @param[in,out] S points to an instance of the Q15 CFFT/CIFFT structure + @param[in] fftLen length of the FFT + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Details + The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. + */ + +ARM_DSP_ATTRIBUTE arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialise the default arm status */ + status = ARM_MATH_SUCCESS; + /* Initialise the FFT length */ + S->fftLen = fftLen; + /* Initialise the Twiddle coefficient pointer */ + S->pTwiddle = (q15_t *) twiddleCoef_4096_q15; + /* Initialise the Flag for selection of CFFT or CIFFT */ + S->ifftFlag = ifftFlag; + /* Initialise the Flag for calculation Bit reversal or not */ + S->bitReverseFlag = bitReverseFlag; + + /* Initializations of structure parameters depending on the FFT length */ + switch (S->fftLen) + { + case 4096U: + /* Initializations of structure parameters for 4096 point FFT */ + + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 1U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 1U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) armBitRevTable; + + break; + + case 1024U: + /* Initializations of structure parameters for 1024 point FFT */ + S->twidCoefModifier = 4U; + S->bitRevFactor = 4U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; + + break; + + case 256U: + /* Initializations of structure parameters for 256 point FFT */ + S->twidCoefModifier = 16U; + S->bitRevFactor = 16U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; + + break; + + case 64U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 64U; + S->bitRevFactor = 64U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; + + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + S->twidCoefModifier = 256U; + S->bitRevFactor = 256U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; + + break; + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + return (status); +} + +/** + @} end of ComplexFFTDeprecated group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_q31.c new file mode 100755 index 0000000..391931e --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_init_q31.c @@ -0,0 +1,144 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix4_init_q31.c + * Description: Radix-4 Decimation in Frequency Q31 FFT & IFFT initialization function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + + @brief Initialization function for the Q31 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed in the future. + @param[in,out] S points to an instance of the Q31 CFFT/CIFFT structure. + @param[in] fftLen length of the FFT. + @param[in] ifftFlag flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Details + The parameter <code>ifftFlag</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + The parameter <code>fftLen</code> Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. +*/ + +ARM_DSP_ATTRIBUTE arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag) +{ + + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialise the default arm status */ + status = ARM_MATH_SUCCESS; + /* Initialise the FFT length */ + S->fftLen = fftLen; + /* Initialise the Twiddle coefficient pointer */ + S->pTwiddle = (q31_t *) twiddleCoef_4096_q31; + /* Initialise the Flag for selection of CFFT or CIFFT */ + S->ifftFlag = ifftFlag; + /* Initialise the Flag for calculation Bit reversal or not */ + S->bitReverseFlag = bitReverseFlag; + + /* Initializations of Instance structure depending on the FFT length */ + switch (S->fftLen) + { + /* Initializations of structure parameters for 4096 point FFT */ + case 4096U: + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 1U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 1U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) armBitRevTable; + break; + + /* Initializations of structure parameters for 1024 point FFT */ + case 1024U: + /* Initialise the twiddle coef modifier value */ + S->twidCoefModifier = 4U; + /* Initialise the bit reversal table modifier */ + S->bitRevFactor = 4U; + /* Initialise the bit reversal table pointer */ + S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; + break; + + case 256U: + /* Initializations of structure parameters for 256 point FFT */ + S->twidCoefModifier = 16U; + S->bitRevFactor = 16U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; + break; + + case 64U: + /* Initializations of structure parameters for 64 point FFT */ + S->twidCoefModifier = 64U; + S->bitRevFactor = 64U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; + break; + + case 16U: + /* Initializations of structure parameters for 16 point FFT */ + S->twidCoefModifier = 256U; + S->bitRevFactor = 256U; + S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; + break; + + default: + /* Reporting argument error if fftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + return (status); +} + +/** + @} end of ComplexFFTDeprecated group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_q15.c new file mode 100755 index 0000000..3567819 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_q15.c @@ -0,0 +1,1818 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix4_q15.c + * Description: This file has function definition of Radix-4 FFT & IFFT function and + * In-place bit reversal using bit reversal table + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_q15( + q15_t * pSrc16, + uint32_t fftLen, + const q15_t * pCoef16, + uint32_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_inverse_q15( + q15_t * pSrc16, + uint32_t fftLen, + const q15_t * pCoef16, + uint32_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_bitreversal_q15( + q15_t * pSrc, + uint32_t fftLen, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + + +/** + @brief Processing function for the Q15 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q15 and will be removed in the future. + @param[in] S points to an instance of the Q15 CFFT/CIFFT structure. + @param[in,out] pSrc points to the complex data buffer. Processing occurs in-place. + + @par Input and output formats: + Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process. + Hence the output format is different for different FFT sizes. + The input and output formats for different FFT sizes and number of bits to upscale are mentioned in the tables below for CFFT and CIFFT: + @par + +| CFFT Size | Input format | Output format | Number of bits to upscale | +| --------: | ------------: | ------------: | ------------------------: | +| 16 | 1.15 | 5.11 | 4 | +| 64 | 1.15 | 7.9 | 6 | +| 256 | 1.15 | 9.7 | 8 | +| 1024 | 1.15 | 11.5 | 10 | + +| CIFFT Size | Input format | Output format | Number of bits to upscale | +| ---------: | ------------: | ------------: | ------------------------: | +| 16 | 1.15 | 5.11 | 0 | +| 64 | 1.15 | 7.9 | 0 | +| 256 | 1.15 | 9.7 | 0 | +| 1024 | 1.15 | 11.5 | 0 | + + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 * S, + q15_t * pSrc) +{ + if (S->ifftFlag == 1U) + { + /* Complex IFFT radix-4 */ + arm_radix4_butterfly_inverse_q15(pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier); + } + else + { + /* Complex FFT radix-4 */ + arm_radix4_butterfly_q15(pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier); + } + + if (S->bitReverseFlag == 1U) + { + /* Bit Reversal */ + arm_bitreversal_q15(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); + } + +} + +/** + @} end of ComplexFFTDeprecated group + */ + +/* + * Radix-4 FFT algorithm used is : + * + * Input real and imaginary data: + * x(n) = xa + j * ya + * x(n+N/4 ) = xb + j * yb + * x(n+N/2 ) = xc + j * yc + * x(n+3N 4) = xd + j * yd + * + * + * Output real and imaginary data: + * x(4r) = xa'+ j * ya' + * x(4r+1) = xb'+ j * yb' + * x(4r+2) = xc'+ j * yc' + * x(4r+3) = xd'+ j * yd' + * + * + * Twiddle factors for radix-4 FFT: + * Wn = co1 + j * (- si1) + * W2n = co2 + j * (- si2) + * W3n = co3 + j * (- si3) + + * The real and imaginary output values for the radix-4 butterfly are + * xa' = xa + xb + xc + xd + * ya' = ya + yb + yc + yd + * xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) + * yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) + * xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) + * yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) + * xd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) + * yd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) + * + */ + +/** + @brief Core function for the Q15 CFFT butterfly process. + @param[in,out] pSrc16 points to the in-place buffer of Q15 data type + @param[in] fftLen length of the FFT + @param[in] pCoef16 points to twiddle coefficient buffer + @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table + */ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_q15( + q15_t * pSrc16, + uint32_t fftLen, + const q15_t * pCoef16, + uint32_t twidCoefModifier) +{ + +#if defined (ARM_MATH_DSP) + + q31_t R, S, T, U; + q31_t C1, C2, C3, out1, out2; + uint32_t n1, n2, ic, i0, j, k; + + q15_t *ptr1; + q15_t *pSi0; + q15_t *pSi1; + q15_t *pSi2; + q15_t *pSi3; + + q31_t xaya, xbyb, xcyc, xdyd; + + /* Total process is divided into three stages */ + + /* process first stage, middle stages, & last stage */ + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* n2 = fftLen/4 */ + n2 >>= 2U; + + /* Index for twiddle coefficient */ + ic = 0U; + + /* Index for input read and output write */ + j = n2; + + pSi0 = pSrc16; + pSi1 = pSi0 + 2 * n2; + pSi2 = pSi1 + 2 * n2; + pSi3 = pSi2 + 2 * n2; + + /* Input is in 1.15(q15) format */ + + /* start of first stage process */ + do + { + /* Butterfly implementation */ + + /* Reading i0, i0+fftLen/2 inputs */ + /* Read ya (real), xa(imag) input */ + T = read_q15x2 (pSi0); + T = __SHADD16(T, 0); /* this is just a SIMD arithmetic shift right by 1 */ + T = __SHADD16(T, 0); /* it turns out doing this twice is 2 cycles, the alternative takes 3 cycles */ +/* + in = ((int16_t) (T & 0xFFFF)) >> 2; // alternative code that takes 3 cycles + T = ((T >> 2) & 0xFFFF0000) | (in & 0xFFFF); +*/ + + /* Read yc (real), xc(imag) input */ + S = read_q15x2 (pSi2); + S = __SHADD16(S, 0); + S = __SHADD16(S, 0); + + /* R = packed((ya + yc), (xa + xc) ) */ + R = __QADD16(T, S); + + /* S = packed((ya - yc), (xa - xc) ) */ + S = __QSUB16(T, S); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* Read yb (real), xb(imag) input */ + T = read_q15x2 (pSi1); + T = __SHADD16(T, 0); + T = __SHADD16(T, 0); + + /* Read yd (real), xd(imag) input */ + U = read_q15x2 (pSi3); + U = __SHADD16(U, 0); + U = __SHADD16(U, 0); + + /* T = packed((yb + yd), (xb + xd) ) */ + T = __QADD16(T, U); + + /* writing the butterfly processed i0 sample */ + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + write_q15x2_ia (&pSi0, __SHADD16(R, T)); + + /* R = packed((ya + yc) - (yb + yd), (xa + xc)- (xb + xd)) */ + R = __QSUB16(R, T); + + /* co2 & si2 are read from SIMD Coefficient pointer */ + C2 = read_q15x2 ((q15_t *) pCoef16 + (4U * ic)); + +#ifndef ARM_MATH_BIG_ENDIAN + /* xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) */ + out1 = __SMUAD(C2, R) >> 16U; + /* yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out2 = __SMUSDX(C2, R); +#else + /* xc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out1 = __SMUSDX(R, C2) >> 16U; + /* yc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) */ + out2 = __SMUAD(C2, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* Reading i0+fftLen/4 */ + /* T = packed(yb, xb) */ + T = read_q15x2 (pSi1); + T = __SHADD16(T, 0); + T = __SHADD16(T, 0); + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* writing output(xc', yc') in little endian format */ + write_q15x2_ia (&pSi1, (q31_t) __PKHBT( out1, out2, 0 )); + + /* Butterfly calculations */ + /* U = packed(yd, xd) */ + U = read_q15x2 (pSi3); + U = __SHADD16(U, 0); + U = __SHADD16(U, 0); + + /* T = packed(yb-yd, xb-xd) */ + T = __QSUB16(T, U); + +#ifndef ARM_MATH_BIG_ENDIAN + /* R = packed((ya-yc) + (xb- xd) , (xa-xc) - (yb-yd)) */ + R = __QASX(S, T); + /* S = packed((ya-yc) - (xb- xd), (xa-xc) + (yb-yd)) */ + S = __QSAX(S, T); +#else + /* R = packed((ya-yc) + (xb- xd) , (xa-xc) - (yb-yd)) */ + R = __QSAX(S, T); + /* S = packed((ya-yc) - (xb- xd), (xa-xc) + (yb-yd)) */ + S = __QASX(S, T); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* co1 & si1 are read from SIMD Coefficient pointer */ + C1 = read_q15x2 ((q15_t *) pCoef16 + (2U * ic)); + /* Butterfly process for the i0+fftLen/2 sample */ + +#ifndef ARM_MATH_BIG_ENDIAN + /* xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) */ + out1 = __SMUAD(C1, S) >> 16U; + /* yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) */ + out2 = __SMUSDX(C1, S); +#else + /* xb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) */ + out1 = __SMUSDX(S, C1) >> 16U; + /* yb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) */ + out2 = __SMUAD(C1, S); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* writing output(xb', yb') in little endian format */ + write_q15x2_ia (&pSi2, __PKHBT( out1, out2, 0 )); + + /* co3 & si3 are read from SIMD Coefficient pointer */ + C3 = read_q15x2 ((q15_t *) pCoef16 + (6U * ic)); + /* Butterfly process for the i0+3fftLen/4 sample */ + +#ifndef ARM_MATH_BIG_ENDIAN + /* xd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) */ + out1 = __SMUAD(C3, R) >> 16U; + /* yd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) */ + out2 = __SMUSDX(C3, R); +#else + /* xd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) */ + out1 = __SMUSDX(R, C3) >> 16U; + /* yd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) */ + out2 = __SMUAD(C3, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* writing output(xd', yd') in little endian format */ + write_q15x2_ia (&pSi3, __PKHBT( out1, out2, 0 )); + + /* Twiddle coefficients index modifier */ + ic = ic + twidCoefModifier; + + } while (--j); + /* data is in 4.11(q11) format */ + + /* end of first stage process */ + + + /* start of middle stage process */ + + /* Twiddle coefficients index modifier */ + twidCoefModifier <<= 2U; + + /* Calculation of Middle stage */ + for (k = fftLen / 4U; k > 4U; k >>= 2U) + { + /* Initializations for the middle stage */ + n1 = n2; + n2 >>= 2U; + ic = 0U; + + for (j = 0U; j <= (n2 - 1U); j++) + { + /* index calculation for the coefficients */ + C1 = read_q15x2 ((q15_t *) pCoef16 + (2U * ic)); + C2 = read_q15x2 ((q15_t *) pCoef16 + (4U * ic)); + C3 = read_q15x2 ((q15_t *) pCoef16 + (6U * ic)); + + /* Twiddle coefficients index modifier */ + ic = ic + twidCoefModifier; + + pSi0 = pSrc16 + 2 * j; + pSi1 = pSi0 + 2 * n2; + pSi2 = pSi1 + 2 * n2; + pSi3 = pSi2 + 2 * n2; + + /* Butterfly implementation */ + for (i0 = j; i0 < fftLen; i0 += n1) + { + /* Reading i0, i0+fftLen/2 inputs */ + /* Read ya (real), xa(imag) input */ + T = read_q15x2 (pSi0); + + /* Read yc (real), xc(imag) input */ + S = read_q15x2 (pSi2); + + /* R = packed( (ya + yc), (xa + xc)) */ + R = __QADD16(T, S); + + /* S = packed((ya - yc), (xa - xc)) */ + S = __QSUB16(T, S); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* Read yb (real), xb(imag) input */ + T = read_q15x2 (pSi1); + + /* Read yd (real), xd(imag) input */ + U = read_q15x2 (pSi3); + + /* T = packed( (yb + yd), (xb + xd)) */ + T = __QADD16(T, U); + + /* writing the butterfly processed i0 sample */ + + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + out1 = __SHADD16(R, T); + out1 = __SHADD16(out1, 0); + write_q15x2 (pSi0, out1); + pSi0 += 2 * n1; + + /* R = packed( (ya + yc) - (yb + yd), (xa + xc) - (xb + xd)) */ + R = __SHSUB16(R, T); + +#ifndef ARM_MATH_BIG_ENDIAN + /* (ya-yb+yc-yd)* (si2) + (xa-xb+xc-xd)* co2 */ + out1 = __SMUAD(C2, R) >> 16U; + + /* (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out2 = __SMUSDX(C2, R); +#else + /* (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out1 = __SMUSDX(R, C2) >> 16U; + + /* (ya-yb+yc-yd)* (si2) + (xa-xb+xc-xd)* co2 */ + out2 = __SMUAD(C2, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* Reading i0+3fftLen/4 */ + /* Read yb (real), xb(imag) input */ + T = read_q15x2 (pSi1); + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) */ + /* yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + write_q15x2 (pSi1, __PKHBT( out1, out2, 0 )); + pSi1 += 2 * n1; + + /* Butterfly calculations */ + + /* Read yd (real), xd(imag) input */ + U = read_q15x2 (pSi3); + + /* T = packed(yb-yd, xb-xd) */ + T = __QSUB16(T, U); + +#ifndef ARM_MATH_BIG_ENDIAN + /* R = packed((ya-yc) + (xb- xd) , (xa-xc) - (yb-yd)) */ + R = __SHASX(S, T); + + /* S = packed((ya-yc) - (xb- xd), (xa-xc) + (yb-yd)) */ + S = __SHSAX(S, T); + + + /* Butterfly process for the i0+fftLen/2 sample */ + out1 = __SMUAD(C1, S) >> 16U; + out2 = __SMUSDX(C1, S); +#else + /* R = packed((ya-yc) + (xb- xd) , (xa-xc) - (yb-yd)) */ + R = __SHSAX(S, T); + + /* S = packed((ya-yc) - (xb- xd), (xa-xc) + (yb-yd)) */ + S = __SHASX(S, T); + + + /* Butterfly process for the i0+fftLen/2 sample */ + out1 = __SMUSDX(S, C1) >> 16U; + out2 = __SMUAD(C1, S); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) */ + /* yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) */ + write_q15x2 (pSi2, __PKHBT( out1, out2, 0 )); + pSi2 += 2 * n1; + + /* Butterfly process for the i0+3fftLen/4 sample */ + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUAD(C3, R) >> 16U; + out2 = __SMUSDX(C3, R); +#else + out1 = __SMUSDX(R, C3) >> 16U; + out2 = __SMUAD(C3, R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* xd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) */ + /* yd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) */ + write_q15x2 (pSi3, __PKHBT( out1, out2, 0 )); + pSi3 += 2 * n1; + } + } + /* Twiddle coefficients index modifier */ + twidCoefModifier <<= 2U; + } + /* end of middle stage process */ + + + /* data is in 10.6(q6) format for the 1024 point */ + /* data is in 8.8(q8) format for the 256 point */ + /* data is in 6.10(q10) format for the 64 point */ + /* data is in 4.12(q12) format for the 16 point */ + + /* Initializations for the last stage */ + j = fftLen >> 2; + + ptr1 = &pSrc16[0]; + + /* start of last stage process */ + + /* Butterfly implementation */ + do + { + /* Read xa (real), ya(imag) input */ + xaya = read_q15x2_ia (&ptr1); + + /* Read xb (real), yb(imag) input */ + xbyb = read_q15x2_ia (&ptr1); + + /* Read xc (real), yc(imag) input */ + xcyc = read_q15x2_ia (&ptr1); + + /* Read xd (real), yd(imag) input */ + xdyd = read_q15x2_ia (&ptr1); + + /* R = packed((ya + yc), (xa + xc)) */ + R = __QADD16(xaya, xcyc); + + /* T = packed((yb + yd), (xb + xd)) */ + T = __QADD16(xbyb, xdyd); + + /* pointer updation for writing */ + ptr1 = ptr1 - 8U; + + + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + write_q15x2_ia (&ptr1, __SHADD16(R, T)); + + /* T = packed((yb + yd), (xb + xd)) */ + T = __QADD16(xbyb, xdyd); + + /* xc' = (xa-xb+xc-xd) */ + /* yc' = (ya-yb+yc-yd) */ + write_q15x2_ia (&ptr1, __SHSUB16(R, T)); + + /* S = packed((ya - yc), (xa - xc)) */ + S = __QSUB16(xaya, xcyc); + + /* Read yd (real), xd(imag) input */ + /* T = packed( (yb - yd), (xb - xd)) */ + U = __QSUB16(xbyb, xdyd); + +#ifndef ARM_MATH_BIG_ENDIAN + /* xb' = (xa+yb-xc-yd) */ + /* yb' = (ya-xb-yc+xd) */ + write_q15x2_ia (&ptr1, __SHSAX(S, U)); + + /* xd' = (xa-yb-xc+yd) */ + /* yd' = (ya+xb-yc-xd) */ + write_q15x2_ia (&ptr1, __SHASX(S, U)); +#else + /* xb' = (xa+yb-xc-yd) */ + /* yb' = (ya-xb-yc+xd) */ + write_q15x2_ia (&ptr1, __SHASX(S, U)); + + /* xd' = (xa-yb-xc+yd) */ + /* yd' = (ya+xb-yc-xd) */ + write_q15x2_ia (&ptr1, __SHSAX(S, U)); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + } while (--j); + + /* end of last stage process */ + + /* output is in 11.5(q5) format for the 1024 point */ + /* output is in 9.7(q7) format for the 256 point */ + /* output is in 7.9(q9) format for the 64 point */ + /* output is in 5.11(q11) format for the 16 point */ + + +#else /* #if defined (ARM_MATH_DSP) */ + + q15_t R0, R1, S0, S1, T0, T1, U0, U1; + q15_t Co1, Si1, Co2, Si2, Co3, Si3, out1, out2; + uint32_t n1, n2, ic, i0, i1, i2, i3, j, k; + + /* Total process is divided into three stages */ + + /* process first stage, middle stages, & last stage */ + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* n2 = fftLen/4 */ + n2 >>= 2U; + + /* Index for twiddle coefficient */ + ic = 0U; + + /* Index for input read and output write */ + i0 = 0U; + j = n2; + + /* Input is in 1.15(q15) format */ + + /* start of first stage process */ + do + { + /* Butterfly implementation */ + + /* index calculation for the input as, */ + /* pSrc16[i0 + 0], pSrc16[i0 + fftLen/4], pSrc16[i0 + fftLen/2], pSrc16[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Reading i0, i0+fftLen/2 inputs */ + + /* input is down scale by 4 to avoid overflow */ + /* Read ya (real), xa(imag) input */ + T0 = pSrc16[i0 * 2U] >> 2U; + T1 = pSrc16[(i0 * 2U) + 1U] >> 2U; + + /* input is down scale by 4 to avoid overflow */ + /* Read yc (real), xc(imag) input */ + S0 = pSrc16[i2 * 2U] >> 2U; + S1 = pSrc16[(i2 * 2U) + 1U] >> 2U; + + /* R0 = (ya + yc) */ + R0 = __SSAT(T0 + S0, 16U); + /* R1 = (xa + xc) */ + R1 = __SSAT(T1 + S1, 16U); + + /* S0 = (ya - yc) */ + S0 = __SSAT(T0 - S0, 16); + /* S1 = (xa - xc) */ + S1 = __SSAT(T1 - S1, 16); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* input is down scale by 4 to avoid overflow */ + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U] >> 2U; + T1 = pSrc16[(i1 * 2U) + 1U] >> 2U; + + /* input is down scale by 4 to avoid overflow */ + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U] >> 2U; + U1 = pSrc16[(i3 * 2U) + 1] >> 2U; + + /* T0 = (yb + yd) */ + T0 = __SSAT(T0 + U0, 16U); + /* T1 = (xb + xd) */ + T1 = __SSAT(T1 + U1, 16U); + + /* writing the butterfly processed i0 sample */ + /* ya' = ya + yb + yc + yd */ + /* xa' = xa + xb + xc + xd */ + pSrc16[i0 * 2U] = (R0 >> 1U) + (T0 >> 1U); + pSrc16[(i0 * 2U) + 1U] = (R1 >> 1U) + (T1 >> 1U); + + /* R0 = (ya + yc) - (yb + yd) */ + /* R1 = (xa + xc) - (xb + xd) */ + R0 = __SSAT(R0 - T0, 16U); + R1 = __SSAT(R1 - T1, 16U); + + /* co2 & si2 are read from Coefficient pointer */ + Co2 = pCoef16[2U * ic * 2U]; + Si2 = pCoef16[(2U * ic * 2U) + 1]; + + /* xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) */ + out1 = (q15_t) ((Co2 * R0 + Si2 * R1) >> 16U); + /* yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out2 = (q15_t) ((-Si2 * R0 + Co2 * R1) >> 16U); + + /* Reading i0+fftLen/4 */ + /* input is down scale by 4 to avoid overflow */ + /* T0 = yb, T1 = xb */ + T0 = pSrc16[i1 * 2U] >> 2; + T1 = pSrc16[(i1 * 2U) + 1] >> 2; + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* writing output(xc', yc') in little endian format */ + pSrc16[i1 * 2U] = out1; + pSrc16[(i1 * 2U) + 1] = out2; + + /* Butterfly calculations */ + /* input is down scale by 4 to avoid overflow */ + /* U0 = yd, U1 = xd */ + U0 = pSrc16[i3 * 2U] >> 2; + U1 = pSrc16[(i3 * 2U) + 1] >> 2; + /* T0 = yb-yd */ + T0 = __SSAT(T0 - U0, 16); + /* T1 = xb-xd */ + T1 = __SSAT(T1 - U1, 16); + + /* R1 = (ya-yc) + (xb- xd), R0 = (xa-xc) - (yb-yd)) */ + R0 = (q15_t) __SSAT((q31_t) (S0 - T1), 16); + R1 = (q15_t) __SSAT((q31_t) (S1 + T0), 16); + + /* S1 = (ya-yc) - (xb- xd), S0 = (xa-xc) + (yb-yd)) */ + S0 = (q15_t) __SSAT(((q31_t) S0 + T1), 16U); + S1 = (q15_t) __SSAT(((q31_t) S1 - T0), 16U); + + /* co1 & si1 are read from Coefficient pointer */ + Co1 = pCoef16[ic * 2U]; + Si1 = pCoef16[(ic * 2U) + 1]; + /* Butterfly process for the i0+fftLen/2 sample */ + /* xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) */ + out1 = (q15_t) ((Si1 * S1 + Co1 * S0) >> 16); + /* yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) */ + out2 = (q15_t) ((-Si1 * S0 + Co1 * S1) >> 16); + + /* writing output(xb', yb') in little endian format */ + pSrc16[i2 * 2U] = out1; + pSrc16[(i2 * 2U) + 1] = out2; + + /* Co3 & si3 are read from Coefficient pointer */ + Co3 = pCoef16[3U * (ic * 2U)]; + Si3 = pCoef16[(3U * (ic * 2U)) + 1]; + /* Butterfly process for the i0+3fftLen/4 sample */ + /* xd' = (xa-yb-xc+yd)* Co3 + (ya+xb-yc-xd)* (si3) */ + out1 = (q15_t) ((Si3 * R1 + Co3 * R0) >> 16U); + /* yd' = (ya+xb-yc-xd)* Co3 - (xa-yb-xc+yd)* (si3) */ + out2 = (q15_t) ((-Si3 * R0 + Co3 * R1) >> 16U); + /* writing output(xd', yd') in little endian format */ + pSrc16[i3 * 2U] = out1; + pSrc16[(i3 * 2U) + 1] = out2; + + /* Twiddle coefficients index modifier */ + ic = ic + twidCoefModifier; + + /* Updating input index */ + i0 = i0 + 1U; + + } while (--j); + /* data is in 4.11(q11) format */ + + /* end of first stage process */ + + + /* start of middle stage process */ + + /* Twiddle coefficients index modifier */ + twidCoefModifier <<= 2U; + + /* Calculation of Middle stage */ + for (k = fftLen / 4U; k > 4U; k >>= 2U) + { + /* Initializations for the middle stage */ + n1 = n2; + n2 >>= 2U; + ic = 0U; + + for (j = 0U; j <= (n2 - 1U); j++) + { + /* index calculation for the coefficients */ + Co1 = pCoef16[ic * 2U]; + Si1 = pCoef16[(ic * 2U) + 1U]; + Co2 = pCoef16[2U * (ic * 2U)]; + Si2 = pCoef16[(2U * (ic * 2U)) + 1U]; + Co3 = pCoef16[3U * (ic * 2U)]; + Si3 = pCoef16[(3U * (ic * 2U)) + 1U]; + + /* Twiddle coefficients index modifier */ + ic = ic + twidCoefModifier; + + /* Butterfly implementation */ + for (i0 = j; i0 < fftLen; i0 += n1) + { + /* index calculation for the input as, */ + /* pSrc16[i0 + 0], pSrc16[i0 + fftLen/4], pSrc16[i0 + fftLen/2], pSrc16[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Reading i0, i0+fftLen/2 inputs */ + /* Read ya (real), xa(imag) input */ + T0 = pSrc16[i0 * 2U]; + T1 = pSrc16[(i0 * 2U) + 1U]; + + /* Read yc (real), xc(imag) input */ + S0 = pSrc16[i2 * 2U]; + S1 = pSrc16[(i2 * 2U) + 1U]; + + /* R0 = (ya + yc), R1 = (xa + xc) */ + R0 = __SSAT(T0 + S0, 16); + R1 = __SSAT(T1 + S1, 16); + + /* S0 = (ya - yc), S1 =(xa - xc) */ + S0 = __SSAT(T0 - S0, 16); + S1 = __SSAT(T1 - S1, 16); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U]; + T1 = pSrc16[(i1 * 2U) + 1U]; + + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U]; + U1 = pSrc16[(i3 * 2U) + 1U]; + + + /* T0 = (yb + yd), T1 = (xb + xd) */ + T0 = __SSAT(T0 + U0, 16); + T1 = __SSAT(T1 + U1, 16); + + /* writing the butterfly processed i0 sample */ + + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + out1 = ((R0 >> 1U) + (T0 >> 1U)) >> 1U; + out2 = ((R1 >> 1U) + (T1 >> 1U)) >> 1U; + + pSrc16[i0 * 2U] = out1; + pSrc16[(2U * i0) + 1U] = out2; + + /* R0 = (ya + yc) - (yb + yd), R1 = (xa + xc) - (xb + xd) */ + R0 = (R0 >> 1U) - (T0 >> 1U); + R1 = (R1 >> 1U) - (T1 >> 1U); + + /* (ya-yb+yc-yd)* (si2) + (xa-xb+xc-xd)* co2 */ + out1 = (q15_t) ((Co2 * R0 + Si2 * R1) >> 16U); + + /* (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out2 = (q15_t) ((-Si2 * R0 + Co2 * R1) >> 16U); + + /* Reading i0+3fftLen/4 */ + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U]; + T1 = pSrc16[(i1 * 2U) + 1U]; + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) */ + /* yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + pSrc16[i1 * 2U] = out1; + pSrc16[(i1 * 2U) + 1U] = out2; + + /* Butterfly calculations */ + + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U]; + U1 = pSrc16[(i3 * 2U) + 1U]; + + /* T0 = yb-yd, T1 = xb-xd */ + T0 = __SSAT(T0 - U0, 16); + T1 = __SSAT(T1 - U1, 16); + + /* R0 = (ya-yc) + (xb- xd), R1 = (xa-xc) - (yb-yd)) */ + R0 = (S0 >> 1U) - (T1 >> 1U); + R1 = (S1 >> 1U) + (T0 >> 1U); + + /* S0 = (ya-yc) - (xb- xd), S1 = (xa-xc) + (yb-yd)) */ + S0 = (S0 >> 1U) + (T1 >> 1U); + S1 = (S1 >> 1U) - (T0 >> 1U); + + /* Butterfly process for the i0+fftLen/2 sample */ + out1 = (q15_t) ((Co1 * S0 + Si1 * S1) >> 16U); + + out2 = (q15_t) ((-Si1 * S0 + Co1 * S1) >> 16U); + + /* xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) */ + /* yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) */ + pSrc16[i2 * 2U] = out1; + pSrc16[(i2 * 2U) + 1U] = out2; + + /* Butterfly process for the i0+3fftLen/4 sample */ + out1 = (q15_t) ((Si3 * R1 + Co3 * R0) >> 16U); + + out2 = (q15_t) ((-Si3 * R0 + Co3 * R1) >> 16U); + /* xd' = (xa-yb-xc+yd)* Co3 + (ya+xb-yc-xd)* (si3) */ + /* yd' = (ya+xb-yc-xd)* Co3 - (xa-yb-xc+yd)* (si3) */ + pSrc16[i3 * 2U] = out1; + pSrc16[(i3 * 2U) + 1U] = out2; + } + } + /* Twiddle coefficients index modifier */ + twidCoefModifier <<= 2U; + } + /* end of middle stage process */ + + + /* data is in 10.6(q6) format for the 1024 point */ + /* data is in 8.8(q8) format for the 256 point */ + /* data is in 6.10(q10) format for the 64 point */ + /* data is in 4.12(q12) format for the 16 point */ + + /* Initializations for the last stage */ + n1 = n2; + n2 >>= 2U; + + /* start of last stage process */ + + /* Butterfly implementation */ + for (i0 = 0U; i0 <= (fftLen - n1); i0 += n1) + { + /* index calculation for the input as, */ + /* pSrc16[i0 + 0], pSrc16[i0 + fftLen/4], pSrc16[i0 + fftLen/2], pSrc16[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Reading i0, i0+fftLen/2 inputs */ + /* Read ya (real), xa(imag) input */ + T0 = pSrc16[i0 * 2U]; + T1 = pSrc16[(i0 * 2U) + 1U]; + + /* Read yc (real), xc(imag) input */ + S0 = pSrc16[i2 * 2U]; + S1 = pSrc16[(i2 * 2U) + 1U]; + + /* R0 = (ya + yc), R1 = (xa + xc) */ + R0 = __SSAT(T0 + S0, 16U); + R1 = __SSAT(T1 + S1, 16U); + + /* S0 = (ya - yc), S1 = (xa - xc) */ + S0 = __SSAT(T0 - S0, 16U); + S1 = __SSAT(T1 - S1, 16U); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U]; + T1 = pSrc16[(i1 * 2U) + 1U]; + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U]; + U1 = pSrc16[(i3 * 2U) + 1U]; + + /* T0 = (yb + yd), T1 = (xb + xd)) */ + T0 = __SSAT(T0 + U0, 16U); + T1 = __SSAT(T1 + U1, 16U); + + /* writing the butterfly processed i0 sample */ + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + pSrc16[i0 * 2U] = (R0 >> 1U) + (T0 >> 1U); + pSrc16[(i0 * 2U) + 1U] = (R1 >> 1U) + (T1 >> 1U); + + /* R0 = (ya + yc) - (yb + yd), R1 = (xa + xc) - (xb + xd) */ + R0 = (R0 >> 1U) - (T0 >> 1U); + R1 = (R1 >> 1U) - (T1 >> 1U); + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U]; + T1 = pSrc16[(i1 * 2U) + 1U]; + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* xc' = (xa-xb+xc-xd) */ + /* yc' = (ya-yb+yc-yd) */ + pSrc16[i1 * 2U] = R0; + pSrc16[(i1 * 2U) + 1U] = R1; + + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U]; + U1 = pSrc16[(i3 * 2U) + 1U]; + /* T0 = (yb - yd), T1 = (xb - xd) */ + T0 = __SSAT(T0 - U0, 16U); + T1 = __SSAT(T1 - U1, 16U); + + /* writing the butterfly processed i0 + fftLen/2 sample */ + /* xb' = (xa+yb-xc-yd) */ + /* yb' = (ya-xb-yc+xd) */ + pSrc16[i2 * 2U] = (S0 >> 1U) + (T1 >> 1U); + pSrc16[(i2 * 2U) + 1U] = (S1 >> 1U) - (T0 >> 1U); + + /* writing the butterfly processed i0 + 3fftLen/4 sample */ + /* xd' = (xa-yb-xc+yd) */ + /* yd' = (ya+xb-yc-xd) */ + pSrc16[i3 * 2U] = (S0 >> 1U) - (T1 >> 1U); + pSrc16[(i3 * 2U) + 1U] = (S1 >> 1U) + (T0 >> 1U); + + } + + /* end of last stage process */ + + /* output is in 11.5(q5) format for the 1024 point */ + /* output is in 9.7(q7) format for the 256 point */ + /* output is in 7.9(q9) format for the 64 point */ + /* output is in 5.11(q11) format for the 16 point */ + +#endif /* #if defined (ARM_MATH_DSP) */ + +} + + +/** + @brief Core function for the Q15 CIFFT butterfly process. + @param[in,out] pSrc16 points to the in-place buffer of Q15 data type + @param[in] fftLen length of the FFT + @param[in] pCoef16 points to twiddle coefficient buffer + @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. + */ + +/* + * Radix-4 IFFT algorithm used is : + * + * CIFFT uses same twiddle coefficients as CFFT function + * x[k] = x[n] + (j)k * x[n + fftLen/4] + (-1)k * x[n+fftLen/2] + (-j)k * x[n+3*fftLen/4] + * + * + * IFFT is implemented with following changes in equations from FFT + * + * Input real and imaginary data: + * x(n) = xa + j * ya + * x(n+N/4 ) = xb + j * yb + * x(n+N/2 ) = xc + j * yc + * x(n+3N 4) = xd + j * yd + * + * + * Output real and imaginary data: + * x(4r) = xa'+ j * ya' + * x(4r+1) = xb'+ j * yb' + * x(4r+2) = xc'+ j * yc' + * x(4r+3) = xd'+ j * yd' + * + * + * Twiddle factors for radix-4 IFFT: + * Wn = co1 + j * (si1) + * W2n = co2 + j * (si2) + * W3n = co3 + j * (si3) + + * The real and imaginary output values for the radix-4 butterfly are + * xa' = xa + xb + xc + xd + * ya' = ya + yb + yc + yd + * xb' = (xa-yb-xc+yd)* co1 - (ya+xb-yc-xd)* (si1) + * yb' = (ya+xb-yc-xd)* co1 + (xa-yb-xc+yd)* (si1) + * xc' = (xa-xb+xc-xd)* co2 - (ya-yb+yc-yd)* (si2) + * yc' = (ya-yb+yc-yd)* co2 + (xa-xb+xc-xd)* (si2) + * xd' = (xa+yb-xc-yd)* co3 - (ya-xb-yc+xd)* (si3) + * yd' = (ya-xb-yc+xd)* co3 + (xa+yb-xc-yd)* (si3) + * + */ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_inverse_q15( + q15_t * pSrc16, + uint32_t fftLen, + const q15_t * pCoef16, + uint32_t twidCoefModifier) +{ + +#if defined (ARM_MATH_DSP) + + q31_t R, S, T, U; + q31_t C1, C2, C3, out1, out2; + uint32_t n1, n2, ic, i0, j, k; + + q15_t *ptr1; + q15_t *pSi0; + q15_t *pSi1; + q15_t *pSi2; + q15_t *pSi3; + + q31_t xaya, xbyb, xcyc, xdyd; + + /* Total process is divided into three stages */ + + /* process first stage, middle stages, & last stage */ + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* n2 = fftLen/4 */ + n2 >>= 2U; + + /* Index for twiddle coefficient */ + ic = 0U; + + /* Index for input read and output write */ + j = n2; + + pSi0 = pSrc16; + pSi1 = pSi0 + 2 * n2; + pSi2 = pSi1 + 2 * n2; + pSi3 = pSi2 + 2 * n2; + + /* Input is in 1.15(q15) format */ + + /* start of first stage process */ + do + { + /* Butterfly implementation */ + + /* Reading i0, i0+fftLen/2 inputs */ + /* Read ya (real), xa(imag) input */ + T = read_q15x2 (pSi0); + T = __SHADD16(T, 0); + T = __SHADD16(T, 0); + + /* Read yc (real), xc(imag) input */ + S = read_q15x2 (pSi2); + S = __SHADD16(S, 0); + S = __SHADD16(S, 0); + + /* R = packed((ya + yc), (xa + xc) ) */ + R = __QADD16(T, S); + + /* S = packed((ya - yc), (xa - xc) ) */ + S = __QSUB16(T, S); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* Read yb (real), xb(imag) input */ + T = read_q15x2 (pSi1); + T = __SHADD16(T, 0); + T = __SHADD16(T, 0); + + /* Read yd (real), xd(imag) input */ + U = read_q15x2 (pSi3); + U = __SHADD16(U, 0); + U = __SHADD16(U, 0); + + /* T = packed((yb + yd), (xb + xd) ) */ + T = __QADD16(T, U); + + /* writing the butterfly processed i0 sample */ + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + write_q15x2_ia (&pSi0, __SHADD16(R, T)); + + /* R = packed((ya + yc) - (yb + yd), (xa + xc)- (xb + xd)) */ + R = __QSUB16(R, T); + + /* co2 & si2 are read from SIMD Coefficient pointer */ + C2 = read_q15x2 ((q15_t *) pCoef16 + (4U * ic)); + +#ifndef ARM_MATH_BIG_ENDIAN + /* xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) */ + out1 = __SMUSD(C2, R) >> 16U; + /* yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out2 = __SMUADX(C2, R); +#else + /* xc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out1 = __SMUADX(C2, R) >> 16U; + /* yc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) */ + out2 = __SMUSD(__QSUB16(0, C2), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* Reading i0+fftLen/4 */ + /* T = packed(yb, xb) */ + T = read_q15x2 (pSi1); + T = __SHADD16(T, 0); + T = __SHADD16(T, 0); + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* writing output(xc', yc') in little endian format */ + write_q15x2_ia (&pSi1, (q31_t) __PKHBT( out1, out2, 0 )); + + /* Butterfly calculations */ + /* U = packed(yd, xd) */ + U = read_q15x2 (pSi3); + U = __SHADD16(U, 0); + U = __SHADD16(U, 0); + + /* T = packed(yb-yd, xb-xd) */ + T = __QSUB16(T, U); + +#ifndef ARM_MATH_BIG_ENDIAN + /* R = packed((ya-yc) + (xb- xd) , (xa-xc) - (yb-yd)) */ + R = __QSAX(S, T); + /* S = packed((ya-yc) + (xb- xd), (xa-xc) - (yb-yd)) */ + S = __QASX(S, T); +#else + /* R = packed((ya-yc) + (xb- xd) , (xa-xc) - (yb-yd)) */ + R = __QASX(S, T); + /* S = packed((ya-yc) - (xb- xd), (xa-xc) + (yb-yd)) */ + S = __QSAX(S, T); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* co1 & si1 are read from SIMD Coefficient pointer */ + C1 = read_q15x2 ((q15_t *) pCoef16 + (2U * ic)); + /* Butterfly process for the i0+fftLen/2 sample */ + +#ifndef ARM_MATH_BIG_ENDIAN + /* xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) */ + out1 = __SMUSD(C1, S) >> 16U; + /* yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) */ + out2 = __SMUADX(C1, S); +#else + /* xb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) */ + out1 = __SMUADX(C1, S) >> 16U; + /* yb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) */ + out2 = __SMUSD(__QSUB16(0, C1), S); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* writing output(xb', yb') in little endian format */ + write_q15x2_ia (&pSi2, __PKHBT( out1, out2, 0 )); + + /* co3 & si3 are read from SIMD Coefficient pointer */ + C3 = read_q15x2 ((q15_t *) pCoef16 + (6U * ic)); + /* Butterfly process for the i0+3fftLen/4 sample */ + +#ifndef ARM_MATH_BIG_ENDIAN + /* xd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) */ + out1 = __SMUSD(C3, R) >> 16U; + /* yd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) */ + out2 = __SMUADX(C3, R); +#else + /* xd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) */ + out1 = __SMUADX(C3, R) >> 16U; + /* yd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) */ + out2 = __SMUSD(__QSUB16(0, C3), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* writing output(xd', yd') in little endian format */ + write_q15x2_ia (&pSi3, __PKHBT( out1, out2, 0 )); + + /* Twiddle coefficients index modifier */ + ic = ic + twidCoefModifier; + + } while (--j); + /* data is in 4.11(q11) format */ + + /* end of first stage process */ + + + /* start of middle stage process */ + + /* Twiddle coefficients index modifier */ + twidCoefModifier <<= 2U; + + /* Calculation of Middle stage */ + for (k = fftLen / 4U; k > 4U; k >>= 2U) + { + /* Initializations for the middle stage */ + n1 = n2; + n2 >>= 2U; + ic = 0U; + + for (j = 0U; j <= (n2 - 1U); j++) + { + /* index calculation for the coefficients */ + C1 = read_q15x2 ((q15_t *) pCoef16 + (2U * ic)); + C2 = read_q15x2 ((q15_t *) pCoef16 + (4U * ic)); + C3 = read_q15x2 ((q15_t *) pCoef16 + (6U * ic)); + + /* Twiddle coefficients index modifier */ + ic = ic + twidCoefModifier; + + pSi0 = pSrc16 + 2 * j; + pSi1 = pSi0 + 2 * n2; + pSi2 = pSi1 + 2 * n2; + pSi3 = pSi2 + 2 * n2; + + /* Butterfly implementation */ + for (i0 = j; i0 < fftLen; i0 += n1) + { + /* Reading i0, i0+fftLen/2 inputs */ + /* Read ya (real), xa(imag) input */ + T = read_q15x2 (pSi0); + + /* Read yc (real), xc(imag) input */ + S = read_q15x2 (pSi2); + + /* R = packed( (ya + yc), (xa + xc)) */ + R = __QADD16(T, S); + + /* S = packed((ya - yc), (xa - xc)) */ + S = __QSUB16(T, S); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* Read yb (real), xb(imag) input */ + T = read_q15x2 (pSi1); + + /* Read yd (real), xd(imag) input */ + U = read_q15x2 (pSi3); + + /* T = packed( (yb + yd), (xb + xd)) */ + T = __QADD16(T, U); + + /* writing the butterfly processed i0 sample */ + + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + out1 = __SHADD16(R, T); + out1 = __SHADD16(out1, 0); + write_q15x2 (pSi0, out1); + pSi0 += 2 * n1; + + /* R = packed( (ya + yc) - (yb + yd), (xa + xc) - (xb + xd)) */ + R = __SHSUB16(R, T); + +#ifndef ARM_MATH_BIG_ENDIAN + /* (ya-yb+yc-yd)* (si2) + (xa-xb+xc-xd)* co2 */ + out1 = __SMUSD(C2, R) >> 16U; + + /* (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out2 = __SMUADX(C2, R); +#else + /* (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + out1 = __SMUADX(R, C2) >> 16U; + + /* (ya-yb+yc-yd)* (si2) + (xa-xb+xc-xd)* co2 */ + out2 = __SMUSD(__QSUB16(0, C2), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* Reading i0+3fftLen/4 */ + /* Read yb (real), xb(imag) input */ + T = read_q15x2 (pSi1); + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) */ + /* yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) */ + write_q15x2 (pSi1, __PKHBT( out1, out2, 0 )); + pSi1 += 2 * n1; + + /* Butterfly calculations */ + + /* Read yd (real), xd(imag) input */ + U = read_q15x2 (pSi3); + + /* T = packed(yb-yd, xb-xd) */ + T = __QSUB16(T, U); + +#ifndef ARM_MATH_BIG_ENDIAN + /* R = packed((ya-yc) + (xb- xd) , (xa-xc) - (yb-yd)) */ + R = __SHSAX(S, T); + + /* S = packed((ya-yc) - (xb- xd), (xa-xc) + (yb-yd)) */ + S = __SHASX(S, T); + + /* Butterfly process for the i0+fftLen/2 sample */ + out1 = __SMUSD(C1, S) >> 16U; + out2 = __SMUADX(C1, S); +#else + /* R = packed((ya-yc) + (xb- xd) , (xa-xc) - (yb-yd)) */ + R = __SHASX(S, T); + + /* S = packed((ya-yc) - (xb- xd), (xa-xc) + (yb-yd)) */ + S = __SHSAX(S, T); + + /* Butterfly process for the i0+fftLen/2 sample */ + out1 = __SMUADX(S, C1) >> 16U; + out2 = __SMUSD(__QSUB16(0, C1), S); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) */ + /* yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) */ + write_q15x2 (pSi2, __PKHBT( out1, out2, 0 )); + pSi2 += 2 * n1; + + /* Butterfly process for the i0+3fftLen/4 sample */ + +#ifndef ARM_MATH_BIG_ENDIAN + out1 = __SMUSD(C3, R) >> 16U; + out2 = __SMUADX(C3, R); +#else + out1 = __SMUADX(C3, R) >> 16U; + out2 = __SMUSD(__QSUB16(0, C3), R); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* xd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) */ + /* yd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) */ + write_q15x2 (pSi3, __PKHBT( out1, out2, 0 )); + pSi3 += 2 * n1; + } + } + /* Twiddle coefficients index modifier */ + twidCoefModifier <<= 2U; + } + /* end of middle stage process */ + + /* data is in 10.6(q6) format for the 1024 point */ + /* data is in 8.8(q8) format for the 256 point */ + /* data is in 6.10(q10) format for the 64 point */ + /* data is in 4.12(q12) format for the 16 point */ + + /* Initializations for the last stage */ + j = fftLen >> 2; + + ptr1 = &pSrc16[0]; + + /* start of last stage process */ + + /* Butterfly implementation */ + do + { + /* Read xa (real), ya(imag) input */ + xaya = read_q15x2_ia (&ptr1); + + /* Read xb (real), yb(imag) input */ + xbyb = read_q15x2_ia (&ptr1); + + /* Read xc (real), yc(imag) input */ + xcyc = read_q15x2_ia (&ptr1); + + /* Read xd (real), yd(imag) input */ + xdyd = read_q15x2_ia (&ptr1); + + /* R = packed((ya + yc), (xa + xc)) */ + R = __QADD16(xaya, xcyc); + + /* T = packed((yb + yd), (xb + xd)) */ + T = __QADD16(xbyb, xdyd); + + /* pointer updation for writing */ + ptr1 = ptr1 - 8U; + + + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + write_q15x2_ia (&ptr1, __SHADD16(R, T)); + + /* T = packed((yb + yd), (xb + xd)) */ + T = __QADD16(xbyb, xdyd); + + /* xc' = (xa-xb+xc-xd) */ + /* yc' = (ya-yb+yc-yd) */ + write_q15x2_ia (&ptr1, __SHSUB16(R, T)); + + /* S = packed((ya - yc), (xa - xc)) */ + S = __QSUB16(xaya, xcyc); + + /* Read yd (real), xd(imag) input */ + /* T = packed( (yb - yd), (xb - xd)) */ + U = __QSUB16(xbyb, xdyd); + +#ifndef ARM_MATH_BIG_ENDIAN + /* xb' = (xa+yb-xc-yd) */ + /* yb' = (ya-xb-yc+xd) */ + write_q15x2_ia (&ptr1, __SHASX(S, U)); + + /* xd' = (xa-yb-xc+yd) */ + /* yd' = (ya+xb-yc-xd) */ + write_q15x2_ia (&ptr1, __SHSAX(S, U)); +#else + /* xb' = (xa+yb-xc-yd) */ + /* yb' = (ya-xb-yc+xd) */ + write_q15x2_ia (&ptr1, __SHSAX(S, U)); + + /* xd' = (xa-yb-xc+yd) */ + /* yd' = (ya+xb-yc-xd) */ + write_q15x2_ia (&ptr1, __SHASX(S, U)); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + } while (--j); + + /* end of last stage process */ + + /* output is in 11.5(q5) format for the 1024 point */ + /* output is in 9.7(q7) format for the 256 point */ + /* output is in 7.9(q9) format for the 64 point */ + /* output is in 5.11(q11) format for the 16 point */ + + +#else /* arm_radix4_butterfly_inverse_q15 */ + + q15_t R0, R1, S0, S1, T0, T1, U0, U1; + q15_t Co1, Si1, Co2, Si2, Co3, Si3, out1, out2; + uint32_t n1, n2, ic, i0, i1, i2, i3, j, k; + + /* Total process is divided into three stages */ + + /* process first stage, middle stages, & last stage */ + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + + /* n2 = fftLen/4 */ + n2 >>= 2U; + + /* Index for twiddle coefficient */ + ic = 0U; + + /* Index for input read and output write */ + i0 = 0U; + + j = n2; + + /* Input is in 1.15(q15) format */ + + /* Start of first stage process */ + do + { + /* Butterfly implementation */ + + /* index calculation for the input as, */ + /* pSrc16[i0 + 0], pSrc16[i0 + fftLen/4], pSrc16[i0 + fftLen/2], pSrc16[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Reading i0, i0+fftLen/2 inputs */ + /* input is down scale by 4 to avoid overflow */ + /* Read ya (real), xa(imag) input */ + T0 = pSrc16[i0 * 2U] >> 2U; + T1 = pSrc16[(i0 * 2U) + 1U] >> 2U; + /* input is down scale by 4 to avoid overflow */ + /* Read yc (real), xc(imag) input */ + S0 = pSrc16[i2 * 2U] >> 2U; + S1 = pSrc16[(i2 * 2U) + 1U] >> 2U; + + /* R0 = (ya + yc), R1 = (xa + xc) */ + R0 = __SSAT(T0 + S0, 16U); + R1 = __SSAT(T1 + S1, 16U); + /* S0 = (ya - yc), S1 = (xa - xc) */ + S0 = __SSAT(T0 - S0, 16U); + S1 = __SSAT(T1 - S1, 16U); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* input is down scale by 4 to avoid overflow */ + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U] >> 2U; + T1 = pSrc16[(i1 * 2U) + 1U] >> 2U; + /* Read yd (real), xd(imag) input */ + /* input is down scale by 4 to avoid overflow */ + U0 = pSrc16[i3 * 2U] >> 2U; + U1 = pSrc16[(i3 * 2U) + 1U] >> 2U; + + /* T0 = (yb + yd), T1 = (xb + xd) */ + T0 = __SSAT(T0 + U0, 16U); + T1 = __SSAT(T1 + U1, 16U); + + /* writing the butterfly processed i0 sample */ + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + pSrc16[i0 * 2U] = (R0 >> 1U) + (T0 >> 1U); + pSrc16[(i0 * 2U) + 1U] = (R1 >> 1U) + (T1 >> 1U); + + /* R0 = (ya + yc) - (yb + yd), R1 = (xa + xc)- (xb + xd) */ + R0 = __SSAT(R0 - T0, 16U); + R1 = __SSAT(R1 - T1, 16U); + /* co2 & si2 are read from Coefficient pointer */ + Co2 = pCoef16[2U * ic * 2U]; + Si2 = pCoef16[(2U * ic * 2U) + 1U]; + /* xc' = (xa-xb+xc-xd)* co2 - (ya-yb+yc-yd)* (si2) */ + out1 = (q15_t) ((Co2 * R0 - Si2 * R1) >> 16U); + /* yc' = (ya-yb+yc-yd)* co2 + (xa-xb+xc-xd)* (si2) */ + out2 = (q15_t) ((Si2 * R0 + Co2 * R1) >> 16U); + + /* Reading i0+fftLen/4 */ + /* input is down scale by 4 to avoid overflow */ + /* T0 = yb, T1 = xb */ + T0 = pSrc16[i1 * 2U] >> 2U; + T1 = pSrc16[(i1 * 2U) + 1U] >> 2U; + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* writing output(xc', yc') in little endian format */ + pSrc16[i1 * 2U] = out1; + pSrc16[(i1 * 2U) + 1U] = out2; + + /* Butterfly calculations */ + /* input is down scale by 4 to avoid overflow */ + /* U0 = yd, U1 = xd) */ + U0 = pSrc16[i3 * 2U] >> 2U; + U1 = pSrc16[(i3 * 2U) + 1U] >> 2U; + + /* T0 = yb-yd, T1 = xb-xd) */ + T0 = __SSAT(T0 - U0, 16U); + T1 = __SSAT(T1 - U1, 16U); + /* R0 = (ya-yc) - (xb- xd) , R1 = (xa-xc) + (yb-yd) */ + R0 = (q15_t) __SSAT((q31_t) (S0 + T1), 16); + R1 = (q15_t) __SSAT((q31_t) (S1 - T0), 16); + /* S = (ya-yc) + (xb- xd), S1 = (xa-xc) - (yb-yd) */ + S0 = (q15_t) __SSAT((q31_t) (S0 - T1), 16); + S1 = (q15_t) __SSAT((q31_t) (S1 + T0), 16); + + /* co1 & si1 are read from Coefficient pointer */ + Co1 = pCoef16[ic * 2U]; + Si1 = pCoef16[(ic * 2U) + 1U]; + /* Butterfly process for the i0+fftLen/2 sample */ + /* xb' = (xa-yb-xc+yd)* co1 - (ya+xb-yc-xd)* (si1) */ + out1 = (q15_t) ((Co1 * S0 - Si1 * S1) >> 16U); + /* yb' = (ya+xb-yc-xd)* co1 + (xa-yb-xc+yd)* (si1) */ + out2 = (q15_t) ((Si1 * S0 + Co1 * S1) >> 16U); + /* writing output(xb', yb') in little endian format */ + pSrc16[i2 * 2U] = out1; + pSrc16[(i2 * 2U) + 1U] = out2; + + /* Co3 & si3 are read from Coefficient pointer */ + Co3 = pCoef16[3U * ic * 2U]; + Si3 = pCoef16[(3U * ic * 2U) + 1U]; + /* Butterfly process for the i0+3fftLen/4 sample */ + /* xd' = (xa+yb-xc-yd)* Co3 - (ya-xb-yc+xd)* (si3) */ + out1 = (q15_t) ((Co3 * R0 - Si3 * R1) >> 16U); + /* yd' = (ya-xb-yc+xd)* Co3 + (xa+yb-xc-yd)* (si3) */ + out2 = (q15_t) ((Si3 * R0 + Co3 * R1) >> 16U); + /* writing output(xd', yd') in little endian format */ + pSrc16[i3 * 2U] = out1; + pSrc16[(i3 * 2U) + 1U] = out2; + + /* Twiddle coefficients index modifier */ + ic = ic + twidCoefModifier; + + /* Updating input index */ + i0 = i0 + 1U; + + } while (--j); + + /* End of first stage process */ + + /* data is in 4.11(q11) format */ + + + /* Start of Middle stage process */ + + /* Twiddle coefficients index modifier */ + twidCoefModifier <<= 2U; + + /* Calculation of Middle stage */ + for (k = fftLen / 4U; k > 4U; k >>= 2U) + { + /* Initializations for the middle stage */ + n1 = n2; + n2 >>= 2U; + ic = 0U; + + for (j = 0U; j <= (n2 - 1U); j++) + { + /* index calculation for the coefficients */ + Co1 = pCoef16[ic * 2U]; + Si1 = pCoef16[(ic * 2U) + 1U]; + Co2 = pCoef16[2U * ic * 2U]; + Si2 = pCoef16[2U * ic * 2U + 1U]; + Co3 = pCoef16[3U * ic * 2U]; + Si3 = pCoef16[(3U * ic * 2U) + 1U]; + + /* Twiddle coefficients index modifier */ + ic = ic + twidCoefModifier; + + /* Butterfly implementation */ + for (i0 = j; i0 < fftLen; i0 += n1) + { + /* index calculation for the input as, */ + /* pSrc16[i0 + 0], pSrc16[i0 + fftLen/4], pSrc16[i0 + fftLen/2], pSrc16[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Reading i0, i0+fftLen/2 inputs */ + /* Read ya (real), xa(imag) input */ + T0 = pSrc16[i0 * 2U]; + T1 = pSrc16[(i0 * 2U) + 1U]; + + /* Read yc (real), xc(imag) input */ + S0 = pSrc16[i2 * 2U]; + S1 = pSrc16[(i2 * 2U) + 1U]; + + + /* R0 = (ya + yc), R1 = (xa + xc) */ + R0 = __SSAT(T0 + S0, 16U); + R1 = __SSAT(T1 + S1, 16U); + /* S0 = (ya - yc), S1 = (xa - xc) */ + S0 = __SSAT(T0 - S0, 16U); + S1 = __SSAT(T1 - S1, 16U); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U]; + T1 = pSrc16[(i1 * 2U) + 1U]; + + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U]; + U1 = pSrc16[(i3 * 2U) + 1U]; + + /* T0 = (yb + yd), T1 = (xb + xd) */ + T0 = __SSAT(T0 + U0, 16U); + T1 = __SSAT(T1 + U1, 16U); + + /* writing the butterfly processed i0 sample */ + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + pSrc16[i0 * 2U] = ((R0 >> 1U) + (T0 >> 1U)) >> 1U; + pSrc16[(i0 * 2U) + 1U] = ((R1 >> 1U) + (T1 >> 1U)) >> 1U; + + /* R0 = (ya + yc) - (yb + yd), R1 = (xa + xc) - (xb + xd) */ + R0 = (R0 >> 1U) - (T0 >> 1U); + R1 = (R1 >> 1U) - (T1 >> 1U); + + /* (ya-yb+yc-yd)* (si2) - (xa-xb+xc-xd)* co2 */ + out1 = (q15_t) ((Co2 * R0 - Si2 * R1) >> 16); + /* (ya-yb+yc-yd)* co2 + (xa-xb+xc-xd)* (si2) */ + out2 = (q15_t) ((Si2 * R0 + Co2 * R1) >> 16); + + /* Reading i0+3fftLen/4 */ + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U]; + T1 = pSrc16[(i1 * 2U) + 1U]; + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* xc' = (xa-xb+xc-xd)* co2 - (ya-yb+yc-yd)* (si2) */ + /* yc' = (ya-yb+yc-yd)* co2 + (xa-xb+xc-xd)* (si2) */ + pSrc16[i1 * 2U] = out1; + pSrc16[(i1 * 2U) + 1U] = out2; + + /* Butterfly calculations */ + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U]; + U1 = pSrc16[(i3 * 2U) + 1U]; + + /* T0 = yb-yd, T1 = xb-xd) */ + T0 = __SSAT(T0 - U0, 16U); + T1 = __SSAT(T1 - U1, 16U); + + /* R0 = (ya-yc) - (xb- xd) , R1 = (xa-xc) + (yb-yd) */ + R0 = (S0 >> 1U) + (T1 >> 1U); + R1 = (S1 >> 1U) - (T0 >> 1U); + + /* S1 = (ya-yc) + (xb- xd), S1 = (xa-xc) - (yb-yd) */ + S0 = (S0 >> 1U) - (T1 >> 1U); + S1 = (S1 >> 1U) + (T0 >> 1U); + + /* Butterfly process for the i0+fftLen/2 sample */ + out1 = (q15_t) ((Co1 * S0 - Si1 * S1) >> 16U); + out2 = (q15_t) ((Si1 * S0 + Co1 * S1) >> 16U); + /* xb' = (xa-yb-xc+yd)* co1 - (ya+xb-yc-xd)* (si1) */ + /* yb' = (ya+xb-yc-xd)* co1 + (xa-yb-xc+yd)* (si1) */ + pSrc16[i2 * 2U] = out1; + pSrc16[(i2 * 2U) + 1U] = out2; + + /* Butterfly process for the i0+3fftLen/4 sample */ + out1 = (q15_t) ((Co3 * R0 - Si3 * R1) >> 16U); + + out2 = (q15_t) ((Si3 * R0 + Co3 * R1) >> 16U); + /* xd' = (xa+yb-xc-yd)* Co3 - (ya-xb-yc+xd)* (si3) */ + /* yd' = (ya-xb-yc+xd)* Co3 + (xa+yb-xc-yd)* (si3) */ + pSrc16[i3 * 2U] = out1; + pSrc16[(i3 * 2U) + 1U] = out2; + + + } + } + /* Twiddle coefficients index modifier */ + twidCoefModifier <<= 2U; + } + /* End of Middle stages process */ + + + /* data is in 10.6(q6) format for the 1024 point */ + /* data is in 8.8(q8) format for the 256 point */ + /* data is in 6.10(q10) format for the 64 point */ + /* data is in 4.12(q12) format for the 16 point */ + + /* start of last stage process */ + + + /* Initializations for the last stage */ + n1 = n2; + n2 >>= 2U; + + /* Butterfly implementation */ + for (i0 = 0U; i0 <= (fftLen - n1); i0 += n1) + { + /* index calculation for the input as, */ + /* pSrc16[i0 + 0], pSrc16[i0 + fftLen/4], pSrc16[i0 + fftLen/2], pSrc16[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Reading i0, i0+fftLen/2 inputs */ + /* Read ya (real), xa(imag) input */ + T0 = pSrc16[i0 * 2U]; + T1 = pSrc16[(i0 * 2U) + 1U]; + /* Read yc (real), xc(imag) input */ + S0 = pSrc16[i2 * 2U]; + S1 = pSrc16[(i2 * 2U) + 1U]; + + /* R0 = (ya + yc), R1 = (xa + xc) */ + R0 = __SSAT(T0 + S0, 16U); + R1 = __SSAT(T1 + S1, 16U); + /* S0 = (ya - yc), S1 = (xa - xc) */ + S0 = __SSAT(T0 - S0, 16U); + S1 = __SSAT(T1 - S1, 16U); + + /* Reading i0+fftLen/4 , i0+3fftLen/4 inputs */ + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U]; + T1 = pSrc16[(i1 * 2U) + 1U]; + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U]; + U1 = pSrc16[(i3 * 2U) + 1U]; + + /* T0 = (yb + yd), T1 = (xb + xd) */ + T0 = __SSAT(T0 + U0, 16U); + T1 = __SSAT(T1 + U1, 16U); + + /* writing the butterfly processed i0 sample */ + /* xa' = xa + xb + xc + xd */ + /* ya' = ya + yb + yc + yd */ + pSrc16[i0 * 2U] = (R0 >> 1U) + (T0 >> 1U); + pSrc16[(i0 * 2U) + 1U] = (R1 >> 1U) + (T1 >> 1U); + + /* R0 = (ya + yc) - (yb + yd), R1 = (xa + xc) - (xb + xd) */ + R0 = (R0 >> 1U) - (T0 >> 1U); + R1 = (R1 >> 1U) - (T1 >> 1U); + + /* Read yb (real), xb(imag) input */ + T0 = pSrc16[i1 * 2U]; + T1 = pSrc16[(i1 * 2U) + 1U]; + + /* writing the butterfly processed i0 + fftLen/4 sample */ + /* xc' = (xa-xb+xc-xd) */ + /* yc' = (ya-yb+yc-yd) */ + pSrc16[i1 * 2U] = R0; + pSrc16[(i1 * 2U) + 1U] = R1; + + /* Read yd (real), xd(imag) input */ + U0 = pSrc16[i3 * 2U]; + U1 = pSrc16[(i3 * 2U) + 1U]; + /* T0 = (yb - yd), T1 = (xb - xd) */ + T0 = __SSAT(T0 - U0, 16U); + T1 = __SSAT(T1 - U1, 16U); + + /* writing the butterfly processed i0 + fftLen/2 sample */ + /* xb' = (xa-yb-xc+yd) */ + /* yb' = (ya+xb-yc-xd) */ + pSrc16[i2 * 2U] = (S0 >> 1U) - (T1 >> 1U); + pSrc16[(i2 * 2U) + 1U] = (S1 >> 1U) + (T0 >> 1U); + + + /* writing the butterfly processed i0 + 3fftLen/4 sample */ + /* xd' = (xa+yb-xc-yd) */ + /* yd' = (ya-xb-yc+xd) */ + pSrc16[i3 * 2U] = (S0 >> 1U) + (T1 >> 1U); + pSrc16[(i3 * 2U) + 1U] = (S1 >> 1U) - (T0 >> 1U); + } + /* end of last stage process */ + + /* output is in 11.5(q5) format for the 1024 point */ + /* output is in 9.7(q7) format for the 256 point */ + /* output is in 7.9(q9) format for the 64 point */ + /* output is in 5.11(q11) format for the 16 point */ + +#endif /* #if defined (ARM_MATH_DSP) */ + +} diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_q31.c new file mode 100755 index 0000000..1cc502b --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix4_q31.c @@ -0,0 +1,837 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix4_q31.c + * Description: This file has function definition of Radix-4 FFT & IFFT function and + * In-place bit reversal using bit reversal table + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_inverse_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint32_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint32_t twidCoefModifier); + +ARM_DSP_ATTRIBUTE void arm_bitreversal_q31( + q31_t * pSrc, + uint32_t fftLen, + uint16_t bitRevFactor, + const uint16_t * pBitRevTab); + + +/** + @addtogroup ComplexFFTDeprecated + @{ + */ + +/** + @brief Processing function for the Q31 CFFT/CIFFT. + @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed in the future. + @param[in] S points to an instance of the Q31 CFFT/CIFFT structure + @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place + + @par Input and output formats: + Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process. + Hence the output format is different for different FFT sizes. + The input and output formats for different FFT sizes and number of bits to upscale are mentioned in the tables below for CFFT and CIFFT: + @par + +| CFFT Size | Input format | Output format | Number of bits to upscale | +| --------: | ------------: | ------------: | ------------------------: | +| 16 | 1.31 | 5.27 | 4 | +| 64 | 1.31 | 7.25 | 6 | +| 256 | 1.31 | 9.23 | 8 | +| 1024 | 1.31 | 11.21 | 10 | + +| CIFFT Size | Input format | Output format | Number of bits to upscale | +| ---------: | ------------: | ------------: | ------------------------: | +| 16 | 1.31 | 5.27 | 0 | +| 64 | 1.31 | 7.25 | 0 | +| 256 | 1.31 | 9.23 | 0 | +| 1024 | 1.31 | 11.21 | 0 | + + */ + +ARM_DSP_ATTRIBUTE void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 * S, + q31_t * pSrc) +{ + if (S->ifftFlag == 1U) + { + /* Complex IFFT radix-4 */ + arm_radix4_butterfly_inverse_q31(pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier); + } + else + { + /* Complex FFT radix-4 */ + arm_radix4_butterfly_q31(pSrc, S->fftLen, S->pTwiddle, S->twidCoefModifier); + } + + if (S->bitReverseFlag == 1U) + { + /* Bit Reversal */ + arm_bitreversal_q31(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable); + } + +} + +/** + @} end of ComplexFFTDeprecated group + */ + +/* + * Radix-4 FFT algorithm used is : + * + * Input real and imaginary data: + * x(n) = xa + j * ya + * x(n+N/4 ) = xb + j * yb + * x(n+N/2 ) = xc + j * yc + * x(n+3N 4) = xd + j * yd + * + * + * Output real and imaginary data: + * x(4r) = xa'+ j * ya' + * x(4r+1) = xb'+ j * yb' + * x(4r+2) = xc'+ j * yc' + * x(4r+3) = xd'+ j * yd' + * + * + * Twiddle factors for radix-4 FFT: + * Wn = co1 + j * (- si1) + * W2n = co2 + j * (- si2) + * W3n = co3 + j * (- si3) + * + * Butterfly implementation: + * xa' = xa + xb + xc + xd + * ya' = ya + yb + yc + yd + * xb' = (xa+yb-xc-yd)* co1 + (ya-xb-yc+xd)* (si1) + * yb' = (ya-xb-yc+xd)* co1 - (xa+yb-xc-yd)* (si1) + * xc' = (xa-xb+xc-xd)* co2 + (ya-yb+yc-yd)* (si2) + * yc' = (ya-yb+yc-yd)* co2 - (xa-xb+xc-xd)* (si2) + * xd' = (xa-yb-xc+yd)* co3 + (ya+xb-yc-xd)* (si3) + * yd' = (ya+xb-yc-xd)* co3 - (xa-yb-xc+yd)* (si3) + * + */ + +/** + @brief Core function for the Q31 CFFT butterfly process. + @param[in,out] pSrc points to the in-place buffer of Q31 data type. + @param[in] fftLen length of the FFT. + @param[in] pCoef points to twiddle coefficient buffer. + @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. + */ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint32_t twidCoefModifier) +{ + uint32_t n1, n2, ia1, ia2, ia3, i0, i1, i2, i3, j, k; + q31_t t1, t2, r1, r2, s1, s2, co1, co2, co3, si1, si2, si3; + + q31_t xa, xb, xc, xd; + q31_t ya, yb, yc, yd; + q31_t xa_out, xb_out, xc_out, xd_out; + q31_t ya_out, yb_out, yc_out, yd_out; + + q31_t *ptr1; + + /* Total process is divided into three stages */ + + /* process first stage, middle stages, & last stage */ + + + /* start of first stage process */ + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + /* n2 = fftLen/4 */ + n2 >>= 2U; + i0 = 0U; + ia1 = 0U; + + j = n2; + + /* Calculation of first stage */ + do + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2U], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* input is in 1.31(q31) format and provide 4 guard bits for the input */ + + /* Butterfly implementation */ + /* xa + xc */ + r1 = (pSrc[(2U * i0)] >> 4U) + (pSrc[(2U * i2)] >> 4U); + /* xa - xc */ + r2 = (pSrc[(2U * i0)] >> 4U) - (pSrc[(2U * i2)] >> 4U); + + /* xb + xd */ + t1 = (pSrc[(2U * i1)] >> 4U) + (pSrc[(2U * i3)] >> 4U); + + /* ya + yc */ + s1 = (pSrc[(2U * i0) + 1U] >> 4U) + (pSrc[(2U * i2) + 1U] >> 4U); + /* ya - yc */ + s2 = (pSrc[(2U * i0) + 1U] >> 4U) - (pSrc[(2U * i2) + 1U] >> 4U); + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = (r1 + t1); + /* (xa + xc) - (xb + xd) */ + r1 = r1 - t1; + /* yb + yd */ + t2 = (pSrc[(2U * i1) + 1U] >> 4U) + (pSrc[(2U * i3) + 1U] >> 4U); + + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (s1 + t2); + + /* (ya + yc) - (yb + yd) */ + s1 = s1 - t2; + + /* yb - yd */ + t1 = (pSrc[(2U * i1) + 1U] >> 4U) - (pSrc[(2U * i3) + 1U] >> 4U); + /* xb - xd */ + t2 = (pSrc[(2U * i1)] >> 4U) - (pSrc[(2U * i3)] >> 4U); + + /* index calculation for the coefficients */ + ia2 = 2U * ia1; + co2 = pCoef[(ia2 * 2U)]; + si2 = pCoef[(ia2 * 2U) + 1U]; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = (((int32_t) (((q63_t) r1 * co2) >> 32)) + + ((int32_t) (((q63_t) s1 * si2) >> 32))) << 1U; + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = (((int32_t) (((q63_t) s1 * co2) >> 32)) - + ((int32_t) (((q63_t) r1 * si2) >> 32))) << 1U; + + /* (xa - xc) + (yb - yd) */ + r1 = r2 + t1; + /* (xa - xc) - (yb - yd) */ + r2 = r2 - t1; + + /* (ya - yc) - (xb - xd) */ + s1 = s2 - t2; + /* (ya - yc) + (xb - xd) */ + s2 = s2 + t2; + + co1 = pCoef[(ia1 * 2U)]; + si1 = pCoef[(ia1 * 2U) + 1U]; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = (((int32_t) (((q63_t) r1 * co1) >> 32)) + + ((int32_t) (((q63_t) s1 * si1) >> 32))) << 1U; + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = (((int32_t) (((q63_t) s1 * co1) >> 32)) - + ((int32_t) (((q63_t) r1 * si1) >> 32))) << 1U; + + /* index calculation for the coefficients */ + ia3 = 3U * ia1; + co3 = pCoef[(ia3 * 2U)]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = (((int32_t) (((q63_t) r2 * co3) >> 32)) + + ((int32_t) (((q63_t) s2 * si3) >> 32))) << 1U; + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = (((int32_t) (((q63_t) s2 * co3) >> 32)) - + ((int32_t) (((q63_t) r2 * si3) >> 32))) << 1U; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + /* Updating input index */ + i0 = i0 + 1U; + + } while (--j); + + /* end of first stage process */ + + /* data is in 5.27(q27) format */ + + + /* start of Middle stages process */ + + + /* each stage in middle stages provides two down scaling of the input */ + + twidCoefModifier <<= 2U; + + + for (k = fftLen / 4U; k > 4U; k >>= 2U) + { + /* Initializations for the first stage */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + /* Calculation of first stage */ + for (j = 0U; j <= (n2 - 1U); j++) + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[(ia1 * 2U)]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[(ia2 * 2U)]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[(ia3 * 2U)]; + si3 = pCoef[(ia3 * 2U) + 1U]; + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + for (i0 = j; i0 < fftLen; i0 += n1) + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2U], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Butterfly implementation */ + /* xa + xc */ + r1 = pSrc[2U * i0] + pSrc[2U * i2]; + /* xa - xc */ + r2 = pSrc[2U * i0] - pSrc[2U * i2]; + + /* ya + yc */ + s1 = pSrc[(2U * i0) + 1U] + pSrc[(2U * i2) + 1U]; + /* ya - yc */ + s2 = pSrc[(2U * i0) + 1U] - pSrc[(2U * i2) + 1U]; + + /* xb + xd */ + t1 = pSrc[2U * i1] + pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = (r1 + t1) >> 2U; + /* xa + xc -(xb + xd) */ + r1 = r1 - t1; + + /* yb + yd */ + t2 = pSrc[(2U * i1) + 1U] + pSrc[(2U * i3) + 1U]; + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (s1 + t2) >> 2U; + + /* (ya + yc) - (yb + yd) */ + s1 = s1 - t2; + + /* (yb - yd) */ + t1 = pSrc[(2U * i1) + 1U] - pSrc[(2U * i3) + 1U]; + /* (xb - xd) */ + t2 = pSrc[2U * i1] - pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 + (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = (((int32_t) (((q63_t) r1 * co2) >> 32)) + + ((int32_t) (((q63_t) s1 * si2) >> 32))) >> 1U; + + /* yc' = (ya-yb+yc-yd)co2 - (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = (((int32_t) (((q63_t) s1 * co2) >> 32)) - + ((int32_t) (((q63_t) r1 * si2) >> 32))) >> 1U; + + /* (xa - xc) + (yb - yd) */ + r1 = r2 + t1; + /* (xa - xc) - (yb - yd) */ + r2 = r2 - t1; + + /* (ya - yc) - (xb - xd) */ + s1 = s2 - t2; + /* (ya - yc) + (xb - xd) */ + s2 = s2 + t2; + + /* xb' = (xa+yb-xc-yd)co1 + (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = (((int32_t) (((q63_t) r1 * co1) >> 32)) + + ((int32_t) (((q63_t) s1 * si1) >> 32))) >> 1U; + + /* yb' = (ya-xb-yc+xd)co1 - (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = (((int32_t) (((q63_t) s1 * co1) >> 32)) - + ((int32_t) (((q63_t) r1 * si1) >> 32))) >> 1U; + + /* xd' = (xa-yb-xc+yd)co3 + (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = (((int32_t) (((q63_t) r2 * co3) >> 32)) + + ((int32_t) (((q63_t) s2 * si3) >> 32))) >> 1U; + + /* yd' = (ya+xb-yc-xd)co3 - (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = (((int32_t) (((q63_t) s2 * co3) >> 32)) - + ((int32_t) (((q63_t) r2 * si3) >> 32))) >> 1U; + } + } + twidCoefModifier <<= 2U; + } + + /* End of Middle stages process */ + + /* data is in 11.21(q21) format for the 1024 point as there are 3 middle stages */ + /* data is in 9.23(q23) format for the 256 point as there are 2 middle stages */ + /* data is in 7.25(q25) format for the 64 point as there are 1 middle stage */ + /* data is in 5.27(q27) format for the 16 point as there are no middle stages */ + + + /* start of Last stage process */ + /* Initializations for the last stage */ + j = fftLen >> 2; + ptr1 = &pSrc[0]; + + /* Calculations of last stage */ + do + { + /* Read xa (real), ya(imag) input */ + xa = *ptr1++; + ya = *ptr1++; + + /* Read xb (real), yb(imag) input */ + xb = *ptr1++; + yb = *ptr1++; + + /* Read xc (real), yc(imag) input */ + xc = *ptr1++; + yc = *ptr1++; + + /* Read xc (real), yc(imag) input */ + xd = *ptr1++; + yd = *ptr1++; + + /* xa' = xa + xb + xc + xd */ + xa_out = xa + xb + xc + xd; + + /* ya' = ya + yb + yc + yd */ + ya_out = ya + yb + yc + yd; + + /* pointer updation for writing */ + ptr1 = ptr1 - 8U; + + /* writing xa' and ya' */ + *ptr1++ = xa_out; + *ptr1++ = ya_out; + + xc_out = (xa - xb + xc - xd); + yc_out = (ya - yb + yc - yd); + + /* writing xc' and yc' */ + *ptr1++ = xc_out; + *ptr1++ = yc_out; + + xb_out = (xa + yb - xc - yd); + yb_out = (ya - xb - yc + xd); + + /* writing xb' and yb' */ + *ptr1++ = xb_out; + *ptr1++ = yb_out; + + xd_out = (xa - yb - xc + yd); + yd_out = (ya + xb - yc - xd); + + /* writing xd' and yd' */ + *ptr1++ = xd_out; + *ptr1++ = yd_out; + + + } while (--j); + + /* output is in 11.21(q21) format for the 1024 point */ + /* output is in 9.23(q23) format for the 256 point */ + /* output is in 7.25(q25) format for the 64 point */ + /* output is in 5.27(q27) format for the 16 point */ + + /* End of last stage process */ + +} + + +/** + @brief Core function for the Q31 CIFFT butterfly process. + @param[in,out] pSrc points to the in-place buffer of Q31 data type. + @param[in] fftLen length of the FFT. + @param[in] pCoef points to twiddle coefficient buffer. + @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. + */ + +/* + * Radix-4 IFFT algorithm used is : + * + * CIFFT uses same twiddle coefficients as CFFT Function + * x[k] = x[n] + (j)k * x[n + fftLen/4] + (-1)k * x[n+fftLen/2] + (-j)k * x[n+3*fftLen/4] + * + * + * IFFT is implemented with following changes in equations from FFT + * + * Input real and imaginary data: + * x(n) = xa + j * ya + * x(n+N/4 ) = xb + j * yb + * x(n+N/2 ) = xc + j * yc + * x(n+3N 4) = xd + j * yd + * + * + * Output real and imaginary data: + * x(4r) = xa'+ j * ya' + * x(4r+1) = xb'+ j * yb' + * x(4r+2) = xc'+ j * yc' + * x(4r+3) = xd'+ j * yd' + * + * + * Twiddle factors for radix-4 IFFT: + * Wn = co1 + j * (si1) + * W2n = co2 + j * (si2) + * W3n = co3 + j * (si3) + + * The real and imaginary output values for the radix-4 butterfly are + * xa' = xa + xb + xc + xd + * ya' = ya + yb + yc + yd + * xb' = (xa-yb-xc+yd)* co1 - (ya+xb-yc-xd)* (si1) + * yb' = (ya+xb-yc-xd)* co1 + (xa-yb-xc+yd)* (si1) + * xc' = (xa-xb+xc-xd)* co2 - (ya-yb+yc-yd)* (si2) + * yc' = (ya-yb+yc-yd)* co2 + (xa-xb+xc-xd)* (si2) + * xd' = (xa+yb-xc-yd)* co3 - (ya-xb-yc+xd)* (si3) + * yd' = (ya-xb-yc+xd)* co3 + (xa+yb-xc-yd)* (si3) + * + */ + +ARM_DSP_ATTRIBUTE void arm_radix4_butterfly_inverse_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pCoef, + uint32_t twidCoefModifier) +{ + uint32_t n1, n2, ia1, ia2, ia3, i0, i1, i2, i3, j, k; + q31_t t1, t2, r1, r2, s1, s2, co1, co2, co3, si1, si2, si3; + q31_t xa, xb, xc, xd; + q31_t ya, yb, yc, yd; + q31_t xa_out, xb_out, xc_out, xd_out; + q31_t ya_out, yb_out, yc_out, yd_out; + + q31_t *ptr1; + + /* input is be 1.31(q31) format for all FFT sizes */ + /* Total process is divided into three stages */ + /* process first stage, middle stages, & last stage */ + + /* Start of first stage process */ + + /* Initializations for the first stage */ + n2 = fftLen; + n1 = n2; + /* n2 = fftLen/4 */ + n2 >>= 2U; + i0 = 0U; + ia1 = 0U; + + j = n2; + + do + { + /* input is in 1.31(q31) format and provide 4 guard bits for the input */ + + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2U], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Butterfly implementation */ + /* xa + xc */ + r1 = (pSrc[2U * i0] >> 4U) + (pSrc[2U * i2] >> 4U); + /* xa - xc */ + r2 = (pSrc[2U * i0] >> 4U) - (pSrc[2U * i2] >> 4U); + + /* xb + xd */ + t1 = (pSrc[2U * i1] >> 4U) + (pSrc[2U * i3] >> 4U); + + /* ya + yc */ + s1 = (pSrc[(2U * i0) + 1U] >> 4U) + (pSrc[(2U * i2) + 1U] >> 4U); + /* ya - yc */ + s2 = (pSrc[(2U * i0) + 1U] >> 4U) - (pSrc[(2U * i2) + 1U] >> 4U); + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = (r1 + t1); + /* (xa + xc) - (xb + xd) */ + r1 = r1 - t1; + /* yb + yd */ + t2 = (pSrc[(2U * i1) + 1U] >> 4U) + (pSrc[(2U * i3) + 1U] >> 4U); + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (s1 + t2); + + /* (ya + yc) - (yb + yd) */ + s1 = s1 - t2; + + /* yb - yd */ + t1 = (pSrc[(2U * i1) + 1U] >> 4U) - (pSrc[(2U * i3) + 1U] >> 4U); + /* xb - xd */ + t2 = (pSrc[2U * i1] >> 4U) - (pSrc[2U * i3] >> 4U); + + /* index calculation for the coefficients */ + ia2 = 2U * ia1; + co2 = pCoef[ia2 * 2U]; + si2 = pCoef[(ia2 * 2U) + 1U]; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = (((int32_t) (((q63_t) r1 * co2) >> 32)) - + ((int32_t) (((q63_t) s1 * si2) >> 32))) << 1U; + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[2U * i1 + 1U] = (((int32_t) (((q63_t) s1 * co2) >> 32)) + + ((int32_t) (((q63_t) r1 * si2) >> 32))) << 1U; + + /* (xa - xc) - (yb - yd) */ + r1 = r2 - t1; + /* (xa - xc) + (yb - yd) */ + r2 = r2 + t1; + + /* (ya - yc) + (xb - xd) */ + s1 = s2 + t2; + /* (ya - yc) - (xb - xd) */ + s2 = s2 - t2; + + co1 = pCoef[ia1 * 2U]; + si1 = pCoef[(ia1 * 2U) + 1U]; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = (((int32_t) (((q63_t) r1 * co1) >> 32)) - + ((int32_t) (((q63_t) s1 * si1) >> 32))) << 1U; + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = (((int32_t) (((q63_t) s1 * co1) >> 32)) + + ((int32_t) (((q63_t) r1 * si1) >> 32))) << 1U; + + /* index calculation for the coefficients */ + ia3 = 3U * ia1; + co3 = pCoef[ia3 * 2U]; + si3 = pCoef[(ia3 * 2U) + 1U]; + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[2U * i3] = (((int32_t) (((q63_t) r2 * co3) >> 32)) - + ((int32_t) (((q63_t) s2 * si3) >> 32))) << 1U; + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = (((int32_t) (((q63_t) s2 * co3) >> 32)) + + ((int32_t) (((q63_t) r2 * si3) >> 32))) << 1U; + + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + /* Updating input index */ + i0 = i0 + 1U; + + } while (--j); + + /* data is in 5.27(q27) format */ + /* each stage provides two down scaling of the input */ + + + /* Start of Middle stages process */ + + twidCoefModifier <<= 2U; + + /* Calculation of second stage to excluding last stage */ + for (k = fftLen / 4U; k > 4U; k >>= 2U) + { + /* Initializations for the first stage */ + n1 = n2; + n2 >>= 2U; + ia1 = 0U; + + for (j = 0; j <= (n2 - 1U); j++) + { + /* index calculation for the coefficients */ + ia2 = ia1 + ia1; + ia3 = ia2 + ia1; + co1 = pCoef[(ia1 * 2U)]; + si1 = pCoef[(ia1 * 2U) + 1U]; + co2 = pCoef[(ia2 * 2U)]; + si2 = pCoef[(ia2 * 2U) + 1U]; + co3 = pCoef[(ia3 * 2U)]; + si3 = pCoef[(ia3 * 2U) + 1U]; + /* Twiddle coefficients index modifier */ + ia1 = ia1 + twidCoefModifier; + + for (i0 = j; i0 < fftLen; i0 += n1) + { + /* index calculation for the input as, */ + /* pSrc[i0 + 0], pSrc[i0 + fftLen/4], pSrc[i0 + fftLen/2U], pSrc[i0 + 3fftLen/4] */ + i1 = i0 + n2; + i2 = i1 + n2; + i3 = i2 + n2; + + /* Butterfly implementation */ + /* xa + xc */ + r1 = pSrc[2U * i0] + pSrc[2U * i2]; + /* xa - xc */ + r2 = pSrc[2U * i0] - pSrc[2U * i2]; + + /* ya + yc */ + s1 = pSrc[(2U * i0) + 1U] + pSrc[(2U * i2) + 1U]; + /* ya - yc */ + s2 = pSrc[(2U * i0) + 1U] - pSrc[(2U * i2) + 1U]; + + /* xb + xd */ + t1 = pSrc[2U * i1] + pSrc[2U * i3]; + + /* xa' = xa + xb + xc + xd */ + pSrc[2U * i0] = (r1 + t1) >> 2U; + /* xa + xc -(xb + xd) */ + r1 = r1 - t1; + /* yb + yd */ + t2 = pSrc[(2U * i1) + 1U] + pSrc[(2U * i3) + 1U]; + /* ya' = ya + yb + yc + yd */ + pSrc[(2U * i0) + 1U] = (s1 + t2) >> 2U; + + /* (ya + yc) - (yb + yd) */ + s1 = s1 - t2; + + /* (yb - yd) */ + t1 = pSrc[(2U * i1) + 1U] - pSrc[(2U * i3) + 1U]; + /* (xb - xd) */ + t2 = pSrc[2U * i1] - pSrc[2U * i3]; + + /* xc' = (xa-xb+xc-xd)co2 - (ya-yb+yc-yd)(si2) */ + pSrc[2U * i1] = (((int32_t) (((q63_t) r1 * co2) >> 32U)) - + ((int32_t) (((q63_t) s1 * si2) >> 32U))) >> 1U; + + /* yc' = (ya-yb+yc-yd)co2 + (xa-xb+xc-xd)(si2) */ + pSrc[(2U * i1) + 1U] = (((int32_t) (((q63_t) s1 * co2) >> 32U)) + + ((int32_t) (((q63_t) r1 * si2) >> 32U))) >> 1U; + + /* (xa - xc) - (yb - yd) */ + r1 = r2 - t1; + /* (xa - xc) + (yb - yd) */ + r2 = r2 + t1; + + /* (ya - yc) + (xb - xd) */ + s1 = s2 + t2; + /* (ya - yc) - (xb - xd) */ + s2 = s2 - t2; + + /* xb' = (xa+yb-xc-yd)co1 - (ya-xb-yc+xd)(si1) */ + pSrc[2U * i2] = (((int32_t) (((q63_t) r1 * co1) >> 32)) - + ((int32_t) (((q63_t) s1 * si1) >> 32))) >> 1U; + + /* yb' = (ya-xb-yc+xd)co1 + (xa+yb-xc-yd)(si1) */ + pSrc[(2U * i2) + 1U] = (((int32_t) (((q63_t) s1 * co1) >> 32)) + + ((int32_t) (((q63_t) r1 * si1) >> 32))) >> 1U; + + /* xd' = (xa-yb-xc+yd)co3 - (ya+xb-yc-xd)(si3) */ + pSrc[(2U * i3)] = (((int32_t) (((q63_t) r2 * co3) >> 32)) - + ((int32_t) (((q63_t) s2 * si3) >> 32))) >> 1U; + + /* yd' = (ya+xb-yc-xd)co3 + (xa-yb-xc+yd)(si3) */ + pSrc[(2U * i3) + 1U] = (((int32_t) (((q63_t) s2 * co3) >> 32)) + + ((int32_t) (((q63_t) r2 * si3) >> 32))) >> 1U; + } + } + twidCoefModifier <<= 2U; + } + + /* End of Middle stages process */ + + /* data is in 11.21(q21) format for the 1024 point as there are 3 middle stages */ + /* data is in 9.23(q23) format for the 256 point as there are 2 middle stages */ + /* data is in 7.25(q25) format for the 64 point as there are 1 middle stage */ + /* data is in 5.27(q27) format for the 16 point as there are no middle stages */ + + + /* Start of last stage process */ + + + /* Initializations for the last stage */ + j = fftLen >> 2; + ptr1 = &pSrc[0]; + + /* Calculations of last stage */ + do + { + /* Read xa (real), ya(imag) input */ + xa = *ptr1++; + ya = *ptr1++; + + /* Read xb (real), yb(imag) input */ + xb = *ptr1++; + yb = *ptr1++; + + /* Read xc (real), yc(imag) input */ + xc = *ptr1++; + yc = *ptr1++; + + /* Read xc (real), yc(imag) input */ + xd = *ptr1++; + yd = *ptr1++; + + /* xa' = xa + xb + xc + xd */ + xa_out = xa + xb + xc + xd; + + /* ya' = ya + yb + yc + yd */ + ya_out = ya + yb + yc + yd; + + /* pointer updation for writing */ + ptr1 = ptr1 - 8U; + + /* writing xa' and ya' */ + *ptr1++ = xa_out; + *ptr1++ = ya_out; + + xc_out = (xa - xb + xc - xd); + yc_out = (ya - yb + yc - yd); + + /* writing xc' and yc' */ + *ptr1++ = xc_out; + *ptr1++ = yc_out; + + xb_out = (xa - yb - xc + yd); + yb_out = (ya + xb - yc - xd); + + /* writing xb' and yb' */ + *ptr1++ = xb_out; + *ptr1++ = yb_out; + + xd_out = (xa + yb - xc - yd); + yd_out = (ya - xb - yc + xd); + + /* writing xd' and yd' */ + *ptr1++ = xd_out; + *ptr1++ = yd_out; + + } while (--j); + + /* output is in 11.21(q21) format for the 1024 point */ + /* output is in 9.23(q23) format for the 256 point */ + /* output is in 7.25(q25) format for the 64 point */ + /* output is in 5.27(q27) format for the 16 point */ + + /* End of last stage process */ +} diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix8_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix8_f16.c new file mode 100755 index 0000000..c700691 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix8_f16.c @@ -0,0 +1,297 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix8_f16.c + * Description: Radix-8 Decimation in Frequency CFFT & CIFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" + +#if defined(ARM_FLOAT16_SUPPORTED) + +void arm_radix8_butterfly_f16( + float16_t * pSrc, + uint16_t fftLen, + const float16_t * pCoef, + uint16_t twidCoefModifier); + +/* ---------------------------------------------------------------------- + * Internal helper function used by the FFTs + * -------------------------------------------------------------------- */ + +/** + brief Core function for the floating-point CFFT butterfly process. + param[in,out] pSrc points to the in-place buffer of floating-point data type. + param[in] fftLen length of the FFT. + param[in] pCoef points to the twiddle coefficient buffer. + param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. + return none +*/ + +ARM_DSP_ATTRIBUTE void arm_radix8_butterfly_f16( + float16_t * pSrc, + uint16_t fftLen, + const float16_t * pCoef, + uint16_t twidCoefModifier) +{ + uint32_t ia1, ia2, ia3, ia4, ia5, ia6, ia7; + uint32_t i1, i2, i3, i4, i5, i6, i7, i8; + uint32_t id; + uint32_t n1, n2, j; + + float16_t r1, r2, r3, r4, r5, r6, r7, r8; + float16_t t1, t2; + float16_t s1, s2, s3, s4, s5, s6, s7, s8; + float16_t p1, p2, p3, p4; + float16_t co2, co3, co4, co5, co6, co7, co8; + float16_t si2, si3, si4, si5, si6, si7, si8; + const float16_t C81 = 0.70710678118f16; + + n2 = fftLen; + + do + { + n1 = n2; + n2 = n2 >> 3; + i1 = 0; + + do + { + i2 = i1 + n2; + i3 = i2 + n2; + i4 = i3 + n2; + i5 = i4 + n2; + i6 = i5 + n2; + i7 = i6 + n2; + i8 = i7 + n2; + r1 = (_Float16)pSrc[2 * i1] + (_Float16)pSrc[2 * i5]; + r5 = (_Float16)pSrc[2 * i1] - (_Float16)pSrc[2 * i5]; + r2 = (_Float16)pSrc[2 * i2] + (_Float16)pSrc[2 * i6]; + r6 = (_Float16)pSrc[2 * i2] - (_Float16)pSrc[2 * i6]; + r3 = (_Float16)pSrc[2 * i3] + (_Float16)pSrc[2 * i7]; + r7 = (_Float16)pSrc[2 * i3] - (_Float16)pSrc[2 * i7]; + r4 = (_Float16)pSrc[2 * i4] + (_Float16)pSrc[2 * i8]; + r8 = (_Float16)pSrc[2 * i4] - (_Float16)pSrc[2 * i8]; + t1 = (_Float16)r1 - (_Float16)r3; + r1 = (_Float16)r1 + (_Float16)r3; + r3 = (_Float16)r2 - (_Float16)r4; + r2 = (_Float16)r2 + (_Float16)r4; + pSrc[2 * i1] = (_Float16)r1 + (_Float16)r2; + pSrc[2 * i5] = (_Float16)r1 - (_Float16)r2; + r1 = (_Float16)pSrc[2 * i1 + 1] + (_Float16)pSrc[2 * i5 + 1]; + s5 = (_Float16)pSrc[2 * i1 + 1] - (_Float16)pSrc[2 * i5 + 1]; + r2 = (_Float16)pSrc[2 * i2 + 1] + (_Float16)pSrc[2 * i6 + 1]; + s6 = (_Float16)pSrc[2 * i2 + 1] - (_Float16)pSrc[2 * i6 + 1]; + s3 = (_Float16)pSrc[2 * i3 + 1] + (_Float16)pSrc[2 * i7 + 1]; + s7 = (_Float16)pSrc[2 * i3 + 1] - (_Float16)pSrc[2 * i7 + 1]; + r4 = (_Float16)pSrc[2 * i4 + 1] + (_Float16)pSrc[2 * i8 + 1]; + s8 = (_Float16)pSrc[2 * i4 + 1] - (_Float16)pSrc[2 * i8 + 1]; + t2 = (_Float16)r1 - (_Float16)s3; + r1 = (_Float16)r1 + (_Float16)s3; + s3 = (_Float16)r2 - (_Float16)r4; + r2 = (_Float16)r2 + (_Float16)r4; + pSrc[2 * i1 + 1] = (_Float16)r1 + (_Float16)r2; + pSrc[2 * i5 + 1] = (_Float16)r1 - (_Float16)r2; + pSrc[2 * i3] = (_Float16)t1 + (_Float16)s3; + pSrc[2 * i7] = (_Float16)t1 - (_Float16)s3; + pSrc[2 * i3 + 1] = (_Float16)t2 - (_Float16)r3; + pSrc[2 * i7 + 1] = (_Float16)t2 + (_Float16)r3; + r1 = ((_Float16)r6 - (_Float16)r8) * (_Float16)C81; + r6 = ((_Float16)r6 + (_Float16)r8) * (_Float16)C81; + r2 = ((_Float16)s6 - (_Float16)s8) * (_Float16)C81; + s6 = ((_Float16)s6 + (_Float16)s8) * (_Float16)C81; + t1 = (_Float16)r5 - (_Float16)r1; + r5 = (_Float16)r5 + (_Float16)r1; + r8 = (_Float16)r7 - (_Float16)r6; + r7 = (_Float16)r7 + (_Float16)r6; + t2 = (_Float16)s5 - (_Float16)r2; + s5 = (_Float16)s5 + (_Float16)r2; + s8 = (_Float16)s7 - (_Float16)s6; + s7 = (_Float16)s7 + (_Float16)s6; + pSrc[2 * i2] = (_Float16)r5 + (_Float16)s7; + pSrc[2 * i8] = (_Float16)r5 - (_Float16)s7; + pSrc[2 * i6] = (_Float16)t1 + (_Float16)s8; + pSrc[2 * i4] = (_Float16)t1 - (_Float16)s8; + pSrc[2 * i2 + 1] = (_Float16)s5 - (_Float16)r7; + pSrc[2 * i8 + 1] = (_Float16)s5 + (_Float16)r7; + pSrc[2 * i6 + 1] = (_Float16)t2 - (_Float16)r8; + pSrc[2 * i4 + 1] = (_Float16)t2 + (_Float16)r8; + + i1 += n1; + } while (i1 < fftLen); + + if (n2 < 8) + break; + + ia1 = 0; + j = 1; + + do + { + /* index calculation for the coefficients */ + id = ia1 + twidCoefModifier; + ia1 = id; + ia2 = ia1 + id; + ia3 = ia2 + id; + ia4 = ia3 + id; + ia5 = ia4 + id; + ia6 = ia5 + id; + ia7 = ia6 + id; + + co2 = pCoef[2 * ia1]; + co3 = pCoef[2 * ia2]; + co4 = pCoef[2 * ia3]; + co5 = pCoef[2 * ia4]; + co6 = pCoef[2 * ia5]; + co7 = pCoef[2 * ia6]; + co8 = pCoef[2 * ia7]; + si2 = pCoef[2 * ia1 + 1]; + si3 = pCoef[2 * ia2 + 1]; + si4 = pCoef[2 * ia3 + 1]; + si5 = pCoef[2 * ia4 + 1]; + si6 = pCoef[2 * ia5 + 1]; + si7 = pCoef[2 * ia6 + 1]; + si8 = pCoef[2 * ia7 + 1]; + + i1 = j; + + do + { + /* index calculation for the input */ + i2 = i1 + n2; + i3 = i2 + n2; + i4 = i3 + n2; + i5 = i4 + n2; + i6 = i5 + n2; + i7 = i6 + n2; + i8 = i7 + n2; + r1 = (_Float16)pSrc[2 * i1] + (_Float16)pSrc[2 * i5]; + r5 = (_Float16)pSrc[2 * i1] - (_Float16)pSrc[2 * i5]; + r2 = (_Float16)pSrc[2 * i2] + (_Float16)pSrc[2 * i6]; + r6 = (_Float16)pSrc[2 * i2] - (_Float16)pSrc[2 * i6]; + r3 = (_Float16)pSrc[2 * i3] + (_Float16)pSrc[2 * i7]; + r7 = (_Float16)pSrc[2 * i3] - (_Float16)pSrc[2 * i7]; + r4 = (_Float16)pSrc[2 * i4] + (_Float16)pSrc[2 * i8]; + r8 = (_Float16)pSrc[2 * i4] - (_Float16)pSrc[2 * i8]; + t1 = (_Float16)r1 - (_Float16)r3; + r1 = (_Float16)r1 + (_Float16)r3; + r3 = (_Float16)r2 - (_Float16)r4; + r2 = (_Float16)r2 + (_Float16)r4; + pSrc[2 * i1] = (_Float16)r1 + (_Float16)r2; + r2 = (_Float16)r1 - (_Float16)r2; + s1 = (_Float16)pSrc[2 * i1 + 1] + (_Float16)pSrc[2 * i5 + 1]; + s5 = (_Float16)pSrc[2 * i1 + 1] - (_Float16)pSrc[2 * i5 + 1]; + s2 = (_Float16)pSrc[2 * i2 + 1] + (_Float16)pSrc[2 * i6 + 1]; + s6 = (_Float16)pSrc[2 * i2 + 1] - (_Float16)pSrc[2 * i6 + 1]; + s3 = (_Float16)pSrc[2 * i3 + 1] + (_Float16)pSrc[2 * i7 + 1]; + s7 = (_Float16)pSrc[2 * i3 + 1] - (_Float16)pSrc[2 * i7 + 1]; + s4 = (_Float16)pSrc[2 * i4 + 1] + (_Float16)pSrc[2 * i8 + 1]; + s8 = (_Float16)pSrc[2 * i4 + 1] - (_Float16)pSrc[2 * i8 + 1]; + t2 = (_Float16)s1 - (_Float16)s3; + s1 = (_Float16)s1 + (_Float16)s3; + s3 = (_Float16)s2 - (_Float16)s4; + s2 = (_Float16)s2 + (_Float16)s4; + r1 = (_Float16)t1 + (_Float16)s3; + t1 = (_Float16)t1 - (_Float16)s3; + pSrc[2 * i1 + 1] = (_Float16)s1 + (_Float16)s2; + s2 = (_Float16)s1 - (_Float16)s2; + s1 = (_Float16)t2 - (_Float16)r3; + t2 = (_Float16)t2 + (_Float16)r3; + p1 = (_Float16)co5 * (_Float16)r2; + p2 = (_Float16)si5 * (_Float16)s2; + p3 = (_Float16)co5 * (_Float16)s2; + p4 = (_Float16)si5 * (_Float16)r2; + pSrc[2 * i5] = (_Float16)p1 + (_Float16)p2; + pSrc[2 * i5 + 1] = (_Float16)p3 - (_Float16)p4; + p1 = (_Float16)co3 * (_Float16)r1; + p2 = (_Float16)si3 * (_Float16)s1; + p3 = (_Float16)co3 * (_Float16)s1; + p4 = (_Float16)si3 * (_Float16)r1; + pSrc[2 * i3] = (_Float16)p1 + (_Float16)p2; + pSrc[2 * i3 + 1] = (_Float16)p3 - (_Float16)p4; + p1 = (_Float16)co7 * (_Float16)t1; + p2 = (_Float16)si7 * (_Float16)t2; + p3 = (_Float16)co7 * (_Float16)t2; + p4 = (_Float16)si7 * (_Float16)t1; + pSrc[2 * i7] = (_Float16)p1 + (_Float16)p2; + pSrc[2 * i7 + 1] = (_Float16)p3 - (_Float16)p4; + r1 = ((_Float16)r6 - (_Float16)r8) * (_Float16)C81; + r6 = ((_Float16)r6 + (_Float16)r8) * (_Float16)C81; + s1 = ((_Float16)s6 - (_Float16)s8) * (_Float16)C81; + s6 = ((_Float16)s6 + (_Float16)s8) * (_Float16)C81; + t1 = (_Float16)r5 - (_Float16)r1; + r5 = (_Float16)r5 + (_Float16)r1; + r8 = (_Float16)r7 - (_Float16)r6; + r7 = (_Float16)r7 + (_Float16)r6; + t2 = (_Float16)s5 - (_Float16)s1; + s5 = (_Float16)s5 + (_Float16)s1; + s8 = (_Float16)s7 - (_Float16)s6; + s7 = (_Float16)s7 + (_Float16)s6; + r1 = (_Float16)r5 + (_Float16)s7; + r5 = (_Float16)r5 - (_Float16)s7; + r6 = (_Float16)t1 + (_Float16)s8; + t1 = (_Float16)t1 - (_Float16)s8; + s1 = (_Float16)s5 - (_Float16)r7; + s5 = (_Float16)s5 + (_Float16)r7; + s6 = (_Float16)t2 - (_Float16)r8; + t2 = (_Float16)t2 + (_Float16)r8; + p1 = (_Float16)co2 * (_Float16)r1; + p2 = (_Float16)si2 * (_Float16)s1; + p3 = (_Float16)co2 * (_Float16)s1; + p4 = (_Float16)si2 * (_Float16)r1; + pSrc[2 * i2] = (_Float16)p1 + (_Float16)p2; + pSrc[2 * i2 + 1] = (_Float16)p3 - (_Float16)p4; + p1 = (_Float16)co8 * (_Float16)r5; + p2 = (_Float16)si8 * (_Float16)s5; + p3 = (_Float16)co8 * (_Float16)s5; + p4 = (_Float16)si8 * (_Float16)r5; + pSrc[2 * i8] = (_Float16)p1 + (_Float16)p2; + pSrc[2 * i8 + 1] = (_Float16)p3 - (_Float16)p4; + p1 = (_Float16)co6 * (_Float16)r6; + p2 = (_Float16)si6 * (_Float16)s6; + p3 = (_Float16)co6 * (_Float16)s6; + p4 = (_Float16)si6 * (_Float16)r6; + pSrc[2 * i6] = (_Float16)p1 + (_Float16)p2; + pSrc[2 * i6 + 1] = (_Float16)p3 - (_Float16)p4; + p1 = (_Float16)co4 * (_Float16)t1; + p2 = (_Float16)si4 * (_Float16)t2; + p3 = (_Float16)co4 * (_Float16)t2; + p4 = (_Float16)si4 * (_Float16)t1; + pSrc[2 * i4] = (_Float16)p1 + (_Float16)p2; + pSrc[2 * i4 + 1] = (_Float16)p3 - (_Float16)p4; + + i1 += n1; + } while (i1 < fftLen); + + j++; + } while (j < n2); + + twidCoefModifier <<= 3; + } while (n2 > 7); +} + +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix8_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix8_f32.c new file mode 100755 index 0000000..5920ccb --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_cfft_radix8_f32.c @@ -0,0 +1,294 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cfft_radix8_f32.c + * Description: Radix-8 Decimation in Frequency CFFT & CIFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + + +/* ---------------------------------------------------------------------- + * Internal helper function used by the FFTs + * -------------------------------------------------------------------- */ + +void arm_radix8_butterfly_f32( + float32_t * pSrc, + uint16_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier); + +/** + brief Core function for the floating-point CFFT butterfly process. + param[in,out] pSrc points to the in-place buffer of floating-point data type. + param[in] fftLen length of the FFT. + param[in] pCoef points to the twiddle coefficient buffer. + param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. + return none +*/ + +ARM_DSP_ATTRIBUTE void arm_radix8_butterfly_f32( + float32_t * pSrc, + uint16_t fftLen, + const float32_t * pCoef, + uint16_t twidCoefModifier) +{ + uint32_t ia1, ia2, ia3, ia4, ia5, ia6, ia7; + uint32_t i1, i2, i3, i4, i5, i6, i7, i8; + uint32_t id; + uint32_t n1, n2, j; + + float32_t r1, r2, r3, r4, r5, r6, r7, r8; + float32_t t1, t2; + float32_t s1, s2, s3, s4, s5, s6, s7, s8; + float32_t p1, p2, p3, p4; + float32_t co2, co3, co4, co5, co6, co7, co8; + float32_t si2, si3, si4, si5, si6, si7, si8; + const float32_t C81 = 0.70710678118f; + + n2 = fftLen; + + do + { + n1 = n2; + n2 = n2 >> 3; + i1 = 0; + + do + { + i2 = i1 + n2; + i3 = i2 + n2; + i4 = i3 + n2; + i5 = i4 + n2; + i6 = i5 + n2; + i7 = i6 + n2; + i8 = i7 + n2; + r1 = pSrc[2 * i1] + pSrc[2 * i5]; + r5 = pSrc[2 * i1] - pSrc[2 * i5]; + r2 = pSrc[2 * i2] + pSrc[2 * i6]; + r6 = pSrc[2 * i2] - pSrc[2 * i6]; + r3 = pSrc[2 * i3] + pSrc[2 * i7]; + r7 = pSrc[2 * i3] - pSrc[2 * i7]; + r4 = pSrc[2 * i4] + pSrc[2 * i8]; + r8 = pSrc[2 * i4] - pSrc[2 * i8]; + t1 = r1 - r3; + r1 = r1 + r3; + r3 = r2 - r4; + r2 = r2 + r4; + pSrc[2 * i1] = r1 + r2; + pSrc[2 * i5] = r1 - r2; + r1 = pSrc[2 * i1 + 1] + pSrc[2 * i5 + 1]; + s5 = pSrc[2 * i1 + 1] - pSrc[2 * i5 + 1]; + r2 = pSrc[2 * i2 + 1] + pSrc[2 * i6 + 1]; + s6 = pSrc[2 * i2 + 1] - pSrc[2 * i6 + 1]; + s3 = pSrc[2 * i3 + 1] + pSrc[2 * i7 + 1]; + s7 = pSrc[2 * i3 + 1] - pSrc[2 * i7 + 1]; + r4 = pSrc[2 * i4 + 1] + pSrc[2 * i8 + 1]; + s8 = pSrc[2 * i4 + 1] - pSrc[2 * i8 + 1]; + t2 = r1 - s3; + r1 = r1 + s3; + s3 = r2 - r4; + r2 = r2 + r4; + pSrc[2 * i1 + 1] = r1 + r2; + pSrc[2 * i5 + 1] = r1 - r2; + pSrc[2 * i3] = t1 + s3; + pSrc[2 * i7] = t1 - s3; + pSrc[2 * i3 + 1] = t2 - r3; + pSrc[2 * i7 + 1] = t2 + r3; + r1 = (r6 - r8) * C81; + r6 = (r6 + r8) * C81; + r2 = (s6 - s8) * C81; + s6 = (s6 + s8) * C81; + t1 = r5 - r1; + r5 = r5 + r1; + r8 = r7 - r6; + r7 = r7 + r6; + t2 = s5 - r2; + s5 = s5 + r2; + s8 = s7 - s6; + s7 = s7 + s6; + pSrc[2 * i2] = r5 + s7; + pSrc[2 * i8] = r5 - s7; + pSrc[2 * i6] = t1 + s8; + pSrc[2 * i4] = t1 - s8; + pSrc[2 * i2 + 1] = s5 - r7; + pSrc[2 * i8 + 1] = s5 + r7; + pSrc[2 * i6 + 1] = t2 - r8; + pSrc[2 * i4 + 1] = t2 + r8; + + i1 += n1; + } while (i1 < fftLen); + + if (n2 < 8) + break; + + ia1 = 0; + j = 1; + + do + { + /* index calculation for the coefficients */ + id = ia1 + twidCoefModifier; + ia1 = id; + ia2 = ia1 + id; + ia3 = ia2 + id; + ia4 = ia3 + id; + ia5 = ia4 + id; + ia6 = ia5 + id; + ia7 = ia6 + id; + + co2 = pCoef[2 * ia1]; + co3 = pCoef[2 * ia2]; + co4 = pCoef[2 * ia3]; + co5 = pCoef[2 * ia4]; + co6 = pCoef[2 * ia5]; + co7 = pCoef[2 * ia6]; + co8 = pCoef[2 * ia7]; + si2 = pCoef[2 * ia1 + 1]; + si3 = pCoef[2 * ia2 + 1]; + si4 = pCoef[2 * ia3 + 1]; + si5 = pCoef[2 * ia4 + 1]; + si6 = pCoef[2 * ia5 + 1]; + si7 = pCoef[2 * ia6 + 1]; + si8 = pCoef[2 * ia7 + 1]; + + i1 = j; + + do + { + /* index calculation for the input */ + i2 = i1 + n2; + i3 = i2 + n2; + i4 = i3 + n2; + i5 = i4 + n2; + i6 = i5 + n2; + i7 = i6 + n2; + i8 = i7 + n2; + r1 = pSrc[2 * i1] + pSrc[2 * i5]; + r5 = pSrc[2 * i1] - pSrc[2 * i5]; + r2 = pSrc[2 * i2] + pSrc[2 * i6]; + r6 = pSrc[2 * i2] - pSrc[2 * i6]; + r3 = pSrc[2 * i3] + pSrc[2 * i7]; + r7 = pSrc[2 * i3] - pSrc[2 * i7]; + r4 = pSrc[2 * i4] + pSrc[2 * i8]; + r8 = pSrc[2 * i4] - pSrc[2 * i8]; + t1 = r1 - r3; + r1 = r1 + r3; + r3 = r2 - r4; + r2 = r2 + r4; + pSrc[2 * i1] = r1 + r2; + r2 = r1 - r2; + s1 = pSrc[2 * i1 + 1] + pSrc[2 * i5 + 1]; + s5 = pSrc[2 * i1 + 1] - pSrc[2 * i5 + 1]; + s2 = pSrc[2 * i2 + 1] + pSrc[2 * i6 + 1]; + s6 = pSrc[2 * i2 + 1] - pSrc[2 * i6 + 1]; + s3 = pSrc[2 * i3 + 1] + pSrc[2 * i7 + 1]; + s7 = pSrc[2 * i3 + 1] - pSrc[2 * i7 + 1]; + s4 = pSrc[2 * i4 + 1] + pSrc[2 * i8 + 1]; + s8 = pSrc[2 * i4 + 1] - pSrc[2 * i8 + 1]; + t2 = s1 - s3; + s1 = s1 + s3; + s3 = s2 - s4; + s2 = s2 + s4; + r1 = t1 + s3; + t1 = t1 - s3; + pSrc[2 * i1 + 1] = s1 + s2; + s2 = s1 - s2; + s1 = t2 - r3; + t2 = t2 + r3; + p1 = co5 * r2; + p2 = si5 * s2; + p3 = co5 * s2; + p4 = si5 * r2; + pSrc[2 * i5] = p1 + p2; + pSrc[2 * i5 + 1] = p3 - p4; + p1 = co3 * r1; + p2 = si3 * s1; + p3 = co3 * s1; + p4 = si3 * r1; + pSrc[2 * i3] = p1 + p2; + pSrc[2 * i3 + 1] = p3 - p4; + p1 = co7 * t1; + p2 = si7 * t2; + p3 = co7 * t2; + p4 = si7 * t1; + pSrc[2 * i7] = p1 + p2; + pSrc[2 * i7 + 1] = p3 - p4; + r1 = (r6 - r8) * C81; + r6 = (r6 + r8) * C81; + s1 = (s6 - s8) * C81; + s6 = (s6 + s8) * C81; + t1 = r5 - r1; + r5 = r5 + r1; + r8 = r7 - r6; + r7 = r7 + r6; + t2 = s5 - s1; + s5 = s5 + s1; + s8 = s7 - s6; + s7 = s7 + s6; + r1 = r5 + s7; + r5 = r5 - s7; + r6 = t1 + s8; + t1 = t1 - s8; + s1 = s5 - r7; + s5 = s5 + r7; + s6 = t2 - r8; + t2 = t2 + r8; + p1 = co2 * r1; + p2 = si2 * s1; + p3 = co2 * s1; + p4 = si2 * r1; + pSrc[2 * i2] = p1 + p2; + pSrc[2 * i2 + 1] = p3 - p4; + p1 = co8 * r5; + p2 = si8 * s5; + p3 = co8 * s5; + p4 = si8 * r5; + pSrc[2 * i8] = p1 + p2; + pSrc[2 * i8 + 1] = p3 - p4; + p1 = co6 * r6; + p2 = si6 * s6; + p3 = co6 * s6; + p4 = si6 * r6; + pSrc[2 * i6] = p1 + p2; + pSrc[2 * i6 + 1] = p3 - p4; + p1 = co4 * t1; + p2 = si4 * t2; + p3 = co4 * t2; + p4 = si4 * t1; + pSrc[2 * i4] = p1 + p2; + pSrc[2 * i4 + 1] = p3 - p4; + + i1 += n1; + } while (i1 < fftLen); + + j++; + } while (j < n2); + + twidCoefModifier <<= 3; + } while (n2 > 7); +} diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_f16.c new file mode 100755 index 0000000..2fd668f --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_f16.c @@ -0,0 +1,181 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_mfcc_f16.c + * Description: MFCC function for the f16 version + * + * $Date: 07 September 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + +#include "dsp/transform_functions_f16.h" +#include "dsp/statistics_functions_f16.h" +#include "dsp/basic_math_functions_f16.h" +#include "dsp/complex_math_functions_f16.h" +#include "dsp/fast_math_functions_f16.h" +#include "dsp/matrix_functions_f16.h" + +#if defined(ARM_FLOAT16_SUPPORTED) + +/** + @ingroup groupTransforms + */ + + +/** + @defgroup MFCC MFCC + + MFCC Transform + + There are separate functions for floating-point, Q15, and Q31 data types. + */ + + + +/** + @addtogroup MFCCF16 + @{ + */ + +/** + @brief MFCC F16 + @param[in] S points to the mfcc instance structure + @param[in] pSrc points to the input samples + @param[out] pDst points to the output MFCC values + @param[inout] pTmp points to a temporary buffer of complex + + @par Description + The number of input samples if the FFT length used + when initializing the instance data structure. + + The source buffer is modified by this function. + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + */ +#if defined(ARM_MATH_NEON_FLOAT16) +ARM_DSP_ATTRIBUTE void arm_mfcc_f16( + const arm_mfcc_instance_f16 * S, + float16_t *pSrc, + float16_t *pDst, + float16_t *pTmp, + float16_t *pTmp2 + ) +#else +ARM_DSP_ATTRIBUTE void arm_mfcc_f16( + const arm_mfcc_instance_f16 * S, + float16_t *pSrc, + float16_t *pDst, + float16_t *pTmp + ) +#endif +{ + float16_t maxValue; + uint32_t index; + uint32_t i; + float16_t result; + const float16_t *coefs=S->filterCoefs; + arm_matrix_instance_f16 pDctMat; + + /* Normalize */ + arm_absmax_f16(pSrc,S->fftLen,&maxValue,&index); + + if ((_Float16)maxValue != 0.0f16) + { + arm_scale_f16(pSrc,1.0f16/(_Float16)maxValue,pSrc,S->fftLen); + } + + /* Multiply by window */ + arm_mult_f16(pSrc,S->windowCoefs,pSrc,S->fftLen); + + /* Compute spectrum magnitude + */ +#if defined(ARM_MATH_NEON_FLOAT16) + arm_rfft_fast_f16(&(S->rfft),pSrc,pTmp,pTmp2,0); + pTmp[1]=0.0f16; +#else +#if defined(ARM_MFCC_USE_CFFT) + /* some HW accelerator for CMSIS-DSP used in some boards + are only providing acceleration for CFFT. + With ARM_MFCC_USE_CFFT enabled, CFFT is used and the MFCC + will be accelerated on those boards. + + The default is to use RFFT + */ + /* Convert from real to complex */ + for(i=0; i < S->fftLen ; i++) + { + pTmp[2*i] = pSrc[i]; + pTmp[2*i+1] = 0.0f16; + } + arm_cfft_f16(&(S->cfft),pTmp,0,1); +#else + /* Default RFFT based implementation */ + arm_rfft_fast_f16(&(S->rfft),pSrc,pTmp,0); + /* Unpack real values */ + pTmp[S->fftLen]=pTmp[1]; + pTmp[S->fftLen+1]=0.0f16; + pTmp[1]=0.0f; +#endif +#endif /* neon */ + arm_cmplx_mag_f16(pTmp,pSrc,S->fftLen); + if ((_Float16)maxValue != 0.0f16) + { + arm_scale_f16(pSrc,maxValue,pSrc,S->fftLen); + } + + /* Apply MEL filters */ + for(i=0; i<S->nbMelFilters; i++) + { + arm_dot_prod_f16(pSrc+S->filterPos[i], + coefs, + S->filterLengths[i], + &result); + + coefs += S->filterLengths[i]; + + pTmp[i] = result; + + } + + /* Compute the log */ + arm_offset_f16(pTmp,1.0e-4f16,pTmp,S->nbMelFilters); + arm_vlog_f16(pTmp,pTmp,S->nbMelFilters); + + /* Multiply with the DCT matrix */ + + pDctMat.numRows=S->nbDctOutputs; + pDctMat.numCols=S->nbMelFilters; + pDctMat.pData=(float16_t*)S->dctCoefs; + + arm_mat_vec_mult_f16(&pDctMat, pTmp, pDst); + + +} +#endif /* defined(ARM_FLOAT16_SUPPORTED) */ +/** + @} end of MFCC group +*/ + diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_f32.c new file mode 100755 index 0000000..6c121a7 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_f32.c @@ -0,0 +1,181 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_mfcc_f32.c + * Description: MFCC function for the f32 version + * + * $Date: 07 September 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + + +#include "dsp/transform_functions.h" +#include "dsp/statistics_functions.h" +#include "dsp/basic_math_functions.h" +#include "dsp/complex_math_functions.h" +#include "dsp/fast_math_functions.h" +#include "dsp/matrix_functions.h" + +/** + @ingroup MFCC + */ + + + +/** + @addtogroup MFCCF32 + @{ + */ + +/** + @brief MFCC F32 + @param[in] S points to the mfcc instance structure + @param[in] pSrc points to the input samples + @param[out] pDst points to the output MFCC values + @param[inout] pTmp points to a temporary buffer of complex + + @par Description + The number of input samples if the FFT length used + when initializing the instance data structure. + + The source buffer is modified by this function. + + @par Neon implementation + The Neon implementation has a different API. + There is an additional temporary buffer pTmp2. + The source buffer is modified. + @code + void arm_mfcc_f32( + const arm_mfcc_instance_f32 * S, + float32_t *pSrc, + float32_t *pDst, + float32_t *pTmp, + float32_t *pTmp2 + ); + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + */ +#if defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE void arm_mfcc_f32( + const arm_mfcc_instance_f32 * S, + float32_t *pSrc, + float32_t *pDst, + float32_t *pTmp, + float32_t *pTmp2 + ) +#else +ARM_DSP_ATTRIBUTE void arm_mfcc_f32( + const arm_mfcc_instance_f32 * S, + float32_t *pSrc, + float32_t *pDst, + float32_t *pTmp + ) +#endif +{ + float32_t maxValue; + uint32_t index; + uint32_t i; + float32_t result; + const float32_t *coefs=S->filterCoefs; + arm_matrix_instance_f32 pDctMat; + + /* Normalize */ + arm_absmax_f32(pSrc,S->fftLen,&maxValue,&index); + + if (maxValue != 0.0f) + { + arm_scale_f32(pSrc,1.0f/maxValue,pSrc,S->fftLen); + } + + /* Multiply by window */ + arm_mult_f32(pSrc,S->windowCoefs,pSrc,S->fftLen); + + /* Compute spectrum magnitude + */ +#if defined(ARM_MATH_NEON) + arm_rfft_fast_f32(&(S->rfft),pSrc,pTmp,pTmp2,0); + pTmp[1]=0.0f; +#else +#if defined(ARM_MFCC_USE_CFFT) + /* some HW accelerator for CMSIS-DSP used in some boards + are only providing acceleration for CFFT. + With ARM_MFCC_USE_CFFT enabled, CFFT is used and the MFCC + will be accelerated on those boards. + + The default is to use RFFT + */ + /* Convert from real to complex */ + for(i=0; i < S->fftLen ; i++) + { + pTmp[2*i] = pSrc[i]; + pTmp[2*i+1] = 0.0f; + } + arm_cfft_f32(&(S->cfft),pTmp,0,1); +#else + /* Default RFFT based implementation */ + arm_rfft_fast_f32(&(S->rfft),pSrc,pTmp,0); + pTmp[1]=0.0f; +#endif /* ARM_MFCC_USE_CFFT */ +#endif /* ARM_MATH_NEON */ + arm_cmplx_mag_f32(pTmp,pSrc,S->fftLen); + if (maxValue != 0.0f) + { + arm_scale_f32(pSrc,maxValue,pSrc,S->fftLen); + } + + /* Apply MEL filters */ + for(i=0; i<S->nbMelFilters; i++) + { + arm_dot_prod_f32(pSrc+S->filterPos[i], + coefs, + S->filterLengths[i], + &result); + + coefs += S->filterLengths[i]; + + pTmp[i] = result; + + } + + /* Compute the log */ + arm_offset_f32(pTmp,1.0e-6f,pTmp,S->nbMelFilters); + arm_vlog_f32(pTmp,pTmp,S->nbMelFilters); + + /* Multiply with the DCT matrix */ + + pDctMat.numRows=S->nbDctOutputs; + pDctMat.numCols=S->nbMelFilters; + pDctMat.pData=(float32_t*)S->dctCoefs; + + arm_mat_vec_mult_f32(&pDctMat, pTmp, pDst); + + +} + +/** + @} end of MFCCF32 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_f16.c new file mode 100755 index 0000000..5f4b91c --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_f16.c @@ -0,0 +1,419 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_mfcc_init_f16.c + * Description: MFCC initialization function for the f16 version + * + * $Date: 07 September 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + +/** + * @defgroup MFCCF16 MFCC F16 + */ + + +/** + @ingroup MFCC + */ + + +/** + @addtogroup MFCCF16 + @{ + */ + + +#include "dsp/transform_functions_f16.h" + +#if defined(ARM_FLOAT16_SUPPORTED) + +/** + @brief Generic initialization of the MFCC F16 instance structure + @param[out] S points to the mfcc instance structure + @param[in] fftLen fft length + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the MFCC sizes + that you need at build time, then it is better to use the initialization + functions defined for each MFCC size. + + */ + +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_f16( + arm_mfcc_instance_f16 * S, + uint32_t fftLen, + uint32_t nbMelFilters, + uint32_t nbDctOutputs, + const float16_t *dctCoefs, + const uint32_t *filterPos, + const uint32_t *filterLengths, + const float16_t *filterCoefs, + const float16_t *windowCoefs + ) +{ + arm_status status; + + S->fftLen=fftLen; + S->nbMelFilters=nbMelFilters; + S->nbDctOutputs=nbDctOutputs; + S->dctCoefs=dctCoefs; + S->filterPos=filterPos; + S->filterLengths=filterLengths; + S->filterCoefs=filterCoefs; + S->windowCoefs=windowCoefs; + + #if defined(ARM_MFCC_USE_CFFT) + status=arm_cfft_init_f16(&(S->cfft),fftLen); + #else + status=arm_rfft_fast_init_f16(&(S->rfft),fftLen); + #endif + + return(status); +} + +#if defined(ARM_MFCC_USE_CFFT) +#define MFCC_INIT_F16(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_##LEN##_f16( \ + arm_mfcc_instance_f16 * S, \ + uint32_t nbMelFilters, \ + uint32_t nbDctOutputs, \ + const float16_t *dctCoefs, \ + const uint32_t *filterPos, \ + const uint32_t *filterLengths, \ + const float16_t *filterCoefs, \ + const float16_t *windowCoefs \ + ) \ +{ \ + arm_status status; \ + \ + S->fftLen=LEN; \ + S->nbMelFilters=nbMelFilters; \ + S->nbDctOutputs=nbDctOutputs; \ + S->dctCoefs=dctCoefs; \ + S->filterPos=filterPos; \ + S->filterLengths=filterLengths; \ + S->filterCoefs=filterCoefs; \ + S->windowCoefs=windowCoefs; \ + \ + status=arm_cfft_init_##LEN##_f16(&(S->cfft));\ + \ + return(status); \ +} +#else +#define MFCC_INIT_F16(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_##LEN##_f16( \ + arm_mfcc_instance_f16 * S, \ + uint32_t nbMelFilters, \ + uint32_t nbDctOutputs, \ + const float16_t *dctCoefs, \ + const uint32_t *filterPos, \ + const uint32_t *filterLengths, \ + const float16_t *filterCoefs, \ + const float16_t *windowCoefs \ + ) \ +{ \ + arm_status status; \ + \ + S->fftLen=LEN; \ + S->nbMelFilters=nbMelFilters; \ + S->nbDctOutputs=nbDctOutputs; \ + S->dctCoefs=dctCoefs; \ + S->filterPos=filterPos; \ + S->filterLengths=filterLengths; \ + S->filterCoefs=filterCoefs; \ + S->windowCoefs=windowCoefs; \ + \ + status=arm_rfft_fast_init_##LEN##_f16(&(S->rfft));\ + \ + return(status); \ +} +#endif + +/** + @brief Initialization of the MFCC F16 instance structure for 32 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. +*/ +MFCC_INIT_F16(32) + +/** + @brief Initialization of the MFCC F16 instance structure for 64 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. +*/ +MFCC_INIT_F16(64) + +/** + @brief Initialization of the MFCC F16 instance structure for 128 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. +*/ +MFCC_INIT_F16(128) + +/** + @brief Initialization of the MFCC F16 instance structure for 256 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. +*/ +MFCC_INIT_F16(256) + +/** + @brief Initialization of the MFCC F16 instance structure for 512 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. +*/ +MFCC_INIT_F16(512) + +/** + @brief Initialization of the MFCC F16 instance structure for 1024 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. +*/ +MFCC_INIT_F16(1024) + +/** + @brief Initialization of the MFCC F16 instance structure for 2048 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. +*/ +MFCC_INIT_F16(2048) + +/** + @brief Initialization of the MFCC F16 instance structure for 4096 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script that can be used + to generate the filter, dct and window arrays. +*/ +MFCC_INIT_F16(4096) + +#endif /* defined(ARM_FLOAT16_SUPPORTED) */ +/** + @} end of MFCCF16 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_f32.c new file mode 100755 index 0000000..001e89f --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_f32.c @@ -0,0 +1,418 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_mfcc_init_f32.c + * Description: MFCC initialization function for the f32 version + * + * $Date: 07 September 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + +/** + * @defgroup MFCCF32 MFCC F32 + */ + + +/** + @ingroup MFCC + */ + + +/** + @addtogroup MFCCF32 + @{ + */ + + +#include "dsp/transform_functions.h" + + + +/** + @brief Generic initialization of the MFCC F32 instance structure + @param[out] S points to the mfcc instance structure + @param[in] fftLen fft length + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the MFCC sizes + that you need at build time, then it is better to use the initialization + functions defined for each MFCC size. + + */ + +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_f32( + arm_mfcc_instance_f32 * S, + uint32_t fftLen, + uint32_t nbMelFilters, + uint32_t nbDctOutputs, + const float32_t *dctCoefs, + const uint32_t *filterPos, + const uint32_t *filterLengths, + const float32_t *filterCoefs, + const float32_t *windowCoefs + ) +{ + arm_status status; + + S->fftLen=fftLen; + S->nbMelFilters=nbMelFilters; + S->nbDctOutputs=nbDctOutputs; + S->dctCoefs=dctCoefs; + S->filterPos=filterPos; + S->filterLengths=filterLengths; + S->filterCoefs=filterCoefs; + S->windowCoefs=windowCoefs; + + #if defined(ARM_MFCC_USE_CFFT) + status=arm_cfft_init_f32(&(S->cfft),fftLen); + #else + status=arm_rfft_fast_init_f32(&(S->rfft),fftLen); + #endif + + return(status); +} + +#if defined(ARM_MFCC_USE_CFFT) +#define MFCC_INIT_F32(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_##LEN##_f32( \ + arm_mfcc_instance_f32 * S, \ + uint32_t nbMelFilters, \ + uint32_t nbDctOutputs, \ + const float32_t *dctCoefs, \ + const uint32_t *filterPos, \ + const uint32_t *filterLengths, \ + const float32_t *filterCoefs, \ + const float32_t *windowCoefs \ + ) \ +{ \ + arm_status status; \ + \ + S->fftLen=LEN; \ + S->nbMelFilters=nbMelFilters; \ + S->nbDctOutputs=nbDctOutputs; \ + S->dctCoefs=dctCoefs; \ + S->filterPos=filterPos; \ + S->filterLengths=filterLengths; \ + S->filterCoefs=filterCoefs; \ + S->windowCoefs=windowCoefs; \ + \ + status=arm_cfft_init_##LEN##_f32(&(S->cfft));\ + \ + return(status); \ +} +#else +#define MFCC_INIT_F32(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_##LEN##_f32( \ + arm_mfcc_instance_f32 * S, \ + uint32_t nbMelFilters, \ + uint32_t nbDctOutputs, \ + const float32_t *dctCoefs, \ + const uint32_t *filterPos, \ + const uint32_t *filterLengths, \ + const float32_t *filterCoefs, \ + const float32_t *windowCoefs \ + ) \ +{ \ + arm_status status; \ + \ + S->fftLen=LEN; \ + S->nbMelFilters=nbMelFilters; \ + S->nbDctOutputs=nbDctOutputs; \ + S->dctCoefs=dctCoefs; \ + S->filterPos=filterPos; \ + S->filterLengths=filterLengths; \ + S->filterCoefs=filterCoefs; \ + S->windowCoefs=windowCoefs; \ + \ + status=arm_rfft_fast_init_##LEN##_f32(&(S->rfft));\ + \ + return(status); \ +} +#endif + +/** + @brief Initialization of the MFCC F32 instance structure for 32 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_F32(32) + +/** + @brief Initialization of the MFCC F32 instance structure for 64 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_F32(64) + +/** + @brief Initialization of the MFCC F32 instance structure for 128 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_F32(128) + +/** + @brief Initialization of the MFCC F32 instance structure for 256 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_F32(256) + +/** + @brief Initialization of the MFCC F32 instance structure for 512 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_F32(512) + +/** + @brief Initialization of the MFCC F32 instance structure for 1024 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_F32(1024) + +/** + @brief Initialization of the MFCC F32 instance structure for 2048 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_F32(2048) + +/** + @brief Initialization of the MFCC F32 instance structure for 4096 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_F32(4096) + +/** + @} end of MFCCF32 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_q15.c new file mode 100755 index 0000000..e464b6e --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_q15.c @@ -0,0 +1,432 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_mfcc_init_q15.c + * Description: MFCC initialization function for the q15 version + * + * $Date: 07 September 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#if defined(ARM_MATH_NEON) +#define RFFT_INIT(L) \ + status=arm_rfft_init_q15(&(S->rfft),L); +#define RFFT_INIT_WITH_LEN(L) \ + status=arm_rfft_init_##L##_q15(&(S->rfft)); +#else +#define RFFT_INIT(L) \ + status=arm_rfft_init_q15(&(S->rfft),L,0,1); +#define RFFT_INIT_WITH_LEN(L) \ + status=arm_rfft_init_##L##_q15(&(S->rfft),0,1); +#endif + + + +/** + * @defgroup MFCCQ15 MFCC Q15 + */ + + +/** + @ingroup MFCC + */ + +/** + @addtogroup MFCCQ15 + @{ + */ + + +#include "dsp/transform_functions.h" + + + +/** + @brief Generic initialization of the MFCC Q15 instance structure + @param[out] S points to the mfcc instance structure + @param[in] fftLen fft length + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the MFCC sizes + that you need at build time, then it is better to use the initialization + functions defined for each MFCC size. + + + */ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_q15( + arm_mfcc_instance_q15 * S, + uint32_t fftLen, + uint32_t nbMelFilters, + uint32_t nbDctOutputs, + const q15_t *dctCoefs, + const uint32_t *filterPos, + const uint32_t *filterLengths, + const q15_t *filterCoefs, + const q15_t *windowCoefs + ) +{ + arm_status status; + + S->fftLen=fftLen; + S->nbMelFilters=nbMelFilters; + S->nbDctOutputs=nbDctOutputs; + S->dctCoefs=dctCoefs; + S->filterPos=filterPos; + S->filterLengths=filterLengths; + S->filterCoefs=filterCoefs; + S->windowCoefs=windowCoefs; + + #if defined(ARM_MFCC_USE_CFFT) + status=arm_cfft_init_q15(&(S->cfft),fftLen); + #else + RFFT_INIT(fftLen); + #endif + + return(status); +} + +#if defined(ARM_MFCC_USE_CFFT) +#define MFCC_INIT_Q15(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_##LEN##_q15( \ + arm_mfcc_instance_q15 * S, \ + uint32_t nbMelFilters, \ + uint32_t nbDctOutputs, \ + const q15_t *dctCoefs, \ + const uint32_t *filterPos, \ + const uint32_t *filterLengths, \ + const q15_t *filterCoefs, \ + const q15_t *windowCoefs \ + ) \ +{ \ + arm_status status; \ + \ + S->fftLen=LEN; \ + S->nbMelFilters=nbMelFilters; \ + S->nbDctOutputs=nbDctOutputs; \ + S->dctCoefs=dctCoefs; \ + S->filterPos=filterPos; \ + S->filterLengths=filterLengths; \ + S->filterCoefs=filterCoefs; \ + S->windowCoefs=windowCoefs; \ + \ + status=arm_cfft_init_##LEN##_q15(&(S->cfft));\ + \ + return(status); \ +} +#else +#define MFCC_INIT_Q15(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_##LEN##_q15( \ + arm_mfcc_instance_q15 * S, \ + uint32_t nbMelFilters, \ + uint32_t nbDctOutputs, \ + const q15_t *dctCoefs, \ + const uint32_t *filterPos, \ + const uint32_t *filterLengths, \ + const q15_t *filterCoefs, \ + const q15_t *windowCoefs \ + ) \ +{ \ + arm_status status; \ + \ + S->fftLen=LEN; \ + S->nbMelFilters=nbMelFilters; \ + S->nbDctOutputs=nbDctOutputs; \ + S->dctCoefs=dctCoefs; \ + S->filterPos=filterPos; \ + S->filterLengths=filterLengths; \ + S->filterCoefs=filterCoefs; \ + S->windowCoefs=windowCoefs; \ + \ + RFFT_INIT_WITH_LEN(LEN); \ + \ + return(status); \ +} +#endif + +/** + @brief Initialization of the MFCC Q15 instance structure for 32 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q15(32) + +/** + @brief Initialization of the MFCC Q15 instance structure for 64 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q15(64) + +/** + @brief Initialization of the MFCC Q15 instance structure for 128 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q15(128) + +/** + @brief Initialization of the MFCC Q15 instance structure for 256 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q15(256) + +/** + @brief Initialization of the MFCC Q15 instance structure for 512 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q15(512) + +/** + @brief Initialization of the MFCC Q15 instance structure for 1024 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q15(1024) + +/** + @brief Initialization of the MFCC Q15 instance structure for 2048 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q15(2048) + +/** + @brief Initialization of the MFCC Q15 instance structure for 4096 samples MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q15(4096) + +#undef RFFT_INIT +#undef RFFT_INIT_WITH_LEN +/** + @} end of MFCCQ15 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_q31.c new file mode 100755 index 0000000..82d0156 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_init_q31.c @@ -0,0 +1,435 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_mfcc_init_q31.c + * Description: MFCC initialization function for the q31 version + * + * $Date: 07 September 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#if defined(ARM_MATH_NEON) +#define RFFT_INIT(L) \ + status=arm_rfft_init_q31(&(S->rfft),L); +#define RFFT_INIT_WITH_LEN(L) \ + status=arm_rfft_init_##L##_q31(&(S->rfft)); +#else +#define RFFT_INIT(L) \ + status=arm_rfft_init_q31(&(S->rfft),L,0,1); +#define RFFT_INIT_WITH_LEN(L) \ + status=arm_rfft_init_##L##_q31(&(S->rfft),0,1); +#endif + + + + +/** + * @defgroup MFCCQ31 MFCC Q31 + */ + + +/** + @ingroup MFCC + */ + + +/** + @addtogroup MFCCQ31 + @{ + */ + + +#include "dsp/transform_functions.h" + + + +/** + @brief Generic initialization of the MFCC Q31 instance structure + @param[out] S points to the mfcc instance structure + @param[in] fftLen fft length + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the MFCC sizes + that you need at build time, then it is better to use the initialization + functions defined for each MFCC size. + + + */ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_q31( + arm_mfcc_instance_q31 * S, + uint32_t fftLen, + uint32_t nbMelFilters, + uint32_t nbDctOutputs, + const q31_t *dctCoefs, + const uint32_t *filterPos, + const uint32_t *filterLengths, + const q31_t *filterCoefs, + const q31_t *windowCoefs + ) +{ + arm_status status; + + S->fftLen=fftLen; + S->nbMelFilters=nbMelFilters; + S->nbDctOutputs=nbDctOutputs; + S->dctCoefs=dctCoefs; + S->filterPos=filterPos; + S->filterLengths=filterLengths; + S->filterCoefs=filterCoefs; + S->windowCoefs=windowCoefs; + + + #if defined(ARM_MFCC_USE_CFFT) + status=arm_cfft_init_q31(&(S->cfft),fftLen); + #else + RFFT_INIT(fftLen); + #endif + + return(status); +} + +#if defined(ARM_MFCC_USE_CFFT) +#define MFCC_INIT_Q31(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_##LEN##_q31( \ + arm_mfcc_instance_q31 * S, \ + uint32_t nbMelFilters, \ + uint32_t nbDctOutputs, \ + const q31_t *dctCoefs, \ + const uint32_t *filterPos, \ + const uint32_t *filterLengths, \ + const q31_t *filterCoefs, \ + const q31_t *windowCoefs \ + ) \ +{ \ + arm_status status; \ + \ + S->fftLen=LEN; \ + S->nbMelFilters=nbMelFilters; \ + S->nbDctOutputs=nbDctOutputs; \ + S->dctCoefs=dctCoefs; \ + S->filterPos=filterPos; \ + S->filterLengths=filterLengths; \ + S->filterCoefs=filterCoefs; \ + S->windowCoefs=windowCoefs; \ + \ + status=arm_cfft_init_##LEN##_q31(&(S->cfft));\ + \ + return(status); \ +} +#else +#define MFCC_INIT_Q31(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_init_##LEN##_q31( \ + arm_mfcc_instance_q31 * S, \ + uint32_t nbMelFilters, \ + uint32_t nbDctOutputs, \ + const q31_t *dctCoefs, \ + const uint32_t *filterPos, \ + const uint32_t *filterLengths, \ + const q31_t *filterCoefs, \ + const q31_t *windowCoefs \ + ) \ +{ \ + arm_status status; \ + \ + S->fftLen=LEN; \ + S->nbMelFilters=nbMelFilters; \ + S->nbDctOutputs=nbDctOutputs; \ + S->dctCoefs=dctCoefs; \ + S->filterPos=filterPos; \ + S->filterLengths=filterLengths; \ + S->filterCoefs=filterCoefs; \ + S->windowCoefs=windowCoefs; \ + \ + RFFT_INIT_WITH_LEN(LEN); \ + \ + return(status); \ +} +#endif + +/** + @brief Initialization of the MFCC Q31 instance structure for 32 sample MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q31(32) + +/** + @brief Initialization of the MFCC Q31 instance structure for 64 sample MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q31(64) + +/** + @brief Initialization of the MFCC Q31 instance structure for 128 sample MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q31(128) + +/** + @brief Initialization of the MFCC Q31 instance structure for 256 sample MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q31(256) + +/** + @brief Initialization of the MFCC Q31 instance structure for 512 sample MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q31(512) + +/** + @brief Initialization of the MFCC Q31 instance structure for 1024 sample MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q31(1024) + +/** + @brief Initialization of the MFCC Q31 instance structure for 2048 sample MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q31(2048) + +/** + @brief Initialization of the MFCC Q31 instance structure for 4096 sample MFCC + @param[out] S points to the mfcc instance structure + @param[in] nbMelFilters number of Mel filters + @param[in] nbDctOutputs number of Dct outputs + @param[in] dctCoefs points to an array of DCT coefficients + @param[in] filterPos points of the array of filter positions + @param[in] filterLengths points to the array of filter lengths + @param[in] filterCoefs points to the array of filter coefficients + @param[in] windowCoefs points to the array of window coefficients + + @return error status + + @par Description + The matrix of Mel filter coefficients is sparse. + Most of the coefficients are zero. + To avoid multiplying the spectrogram by those zeros, the + filter is applied only to a given position in the spectrogram + and on a given number of FFT bins (the filter length). + It is the reason for the arrays filterPos and filterLengths. + + window coefficients can describe (for instance) a Hamming window. + The array has the same size as the FFT length. + + The folder Scripts is containing a Python script which can be used + to generate the filter, dct and window arrays. + */ +MFCC_INIT_Q31(4096) + +#undef RFFT_INIT +#undef RFFT_INIT_WITH_LEN +/** + @} end of MFCCQ31 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_q15.c new file mode 100755 index 0000000..4037339 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_q15.c @@ -0,0 +1,234 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_mfcc_q15.c + * Description: MFCC function for the q15 version + * + * $Date: 07 September 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + + +#include "dsp/transform_functions.h" +#include "dsp/statistics_functions.h" +#include "dsp/basic_math_functions.h" +#include "dsp/complex_math_functions.h" +#include "dsp/fast_math_functions.h" +#include "dsp/matrix_functions.h" + +/* Constants for Q15 implementation */ +#define LOG2TOLOG_Q15 0x02C5C860 +#define MICRO_Q15 0x00000219 +#define SHIFT_MELFILTER_SATURATION_Q15 10 +/** + @ingroup MFCC + */ + + + +/** + @addtogroup MFCCQ15 + @{ + */ + +/** + @brief MFCC Q15 + @param[in] S points to the mfcc instance structure + @param[in] pSrc points to the input samples in Q15 + @param[out] pDst points to the output MFCC values in q8.7 format + @param[inout] pTmp points to a temporary buffer of complex + @return error status + + @par Description + The number of input samples is the FFT length used + when initializing the instance data structure. + + The source buffer is modified by this function. + + The function may saturate. If the FFT length is too + big and the number of MEL filters too small then the fixed + point computations may saturate. + + @par Neon implementation + There is an additional temporary buffer used for the RFFT. + + + @code + arm_status arm_mfcc_q15( + const arm_mfcc_instance_q15 * S, + q15_t *pSrc, + q15_t *pDst, + q31_t *pTmp, + q15_t *pTmp_rfft + ) + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + + */ +#if defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_q15( + const arm_mfcc_instance_q15 * S, + q15_t *pSrc, + q15_t *pDst, + q31_t *pTmp, + q15_t *pTmp_rfft + ) +#else +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_q15( + const arm_mfcc_instance_q15 * S, + q15_t *pSrc, + q15_t *pDst, + q31_t *pTmp + ) +#endif +{ + q15_t m; + uint32_t index; + uint32_t fftShift=0; + q31_t logExponent; + q63_t result; + arm_matrix_instance_q15 pDctMat; + uint32_t i; + uint32_t coefsPos; + uint32_t filterLimit; + q15_t *pTmp2=(q15_t*)pTmp; + + arm_status status = ARM_MATH_SUCCESS; + + // q15 + arm_absmax_q15(pSrc,S->fftLen,&m,&index); + + if ((m != 0) && (m != 0x7FFF)) + { + q15_t quotient; + int16_t shift; + + status = arm_divide_q15(0x7FFF,m,"ient,&shift); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + + arm_scale_q15(pSrc,quotient,shift,pSrc,S->fftLen); + } + + + // q15 + arm_mult_q15(pSrc,S->windowCoefs, pSrc, S->fftLen); + + + /* Compute spectrum magnitude + */ + fftShift = 31 - __CLZ(S->fftLen); +#if defined(ARM_MATH_NEON) + /* Default RFFT based implementation */ + arm_rfft_q15(&(S->rfft),pSrc,pTmp2,pTmp_rfft,0); +#else +#if defined(ARM_MFCC_USE_CFFT) + /* some HW accelerator for CMSIS-DSP used in some boards + are only providing acceleration for CFFT. + With ARM_MFCC_USE_CFFT enabled, CFFT is used and the MFCC + will be accelerated on those boards. + + The default is to use RFFT + */ + /* Convert from real to complex */ + for(i=0; i < S->fftLen ; i++) + { + pTmp2[2*i] = pSrc[i]; + pTmp2[2*i+1] = 0; + } + arm_cfft_q15(&(S->cfft),pTmp2,0,1); +#else + /* Default RFFT based implementation */ + arm_rfft_q15(&(S->rfft),pSrc,pTmp2); +#endif +#endif + filterLimit = 1 + (S->fftLen >> 1); + + + // q15 - fftShift + arm_cmplx_mag_q15(pTmp2,pSrc,filterLimit); + // q14 - fftShift + + /* Apply MEL filters */ + coefsPos = 0; + for(i=0; i<S->nbMelFilters; i++) + { + arm_dot_prod_q15(pSrc+S->filterPos[i], + &(S->filterCoefs[coefsPos]), + S->filterLengths[i], + &result); + + coefsPos += S->filterLengths[i]; + + // q34.29 - fftShift + result += MICRO_Q15; + result >>= SHIFT_MELFILTER_SATURATION_Q15; + // q34.29 - fftShift - satShift + pTmp[i] = __SSAT(result,31) ; + + } + + if ((m != 0) && (m != 0x7FFF)) + { + arm_scale_q31(pTmp,m<<16,0,pTmp,S->nbMelFilters); + } + + // q34.29 - fftShift - satShift + /* Compute the log */ + arm_vlog_q31(pTmp,pTmp,S->nbMelFilters); + + + // q5.26 + + logExponent = fftShift + 2 + SHIFT_MELFILTER_SATURATION_Q15; + logExponent = logExponent * LOG2TOLOG_Q15; + + + // q8.26 + arm_offset_q31(pTmp,logExponent,pTmp,S->nbMelFilters); + arm_shift_q31(pTmp,-19,pTmp,S->nbMelFilters); + for(i=0; i<S->nbMelFilters; i++) + { + pSrc[i] = __SSAT((q15_t)pTmp[i],16); + } + + // q8.7 + + pDctMat.numRows=S->nbDctOutputs; + pDctMat.numCols=S->nbMelFilters; + pDctMat.pData=(q15_t*)S->dctCoefs; + + arm_mat_vec_mult_q15(&pDctMat, pSrc, pDst); + + return(status); +} + +/** + @} end of MFCCQ15 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_q31.c new file mode 100755 index 0000000..043d408 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_mfcc_q31.c @@ -0,0 +1,233 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_mfcc_q31.c + * Description: MFCC function for the q31 version + * + * $Date: 07 September 2021 + * $Revision: V1.10.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + + + +#include "dsp/transform_functions.h" +#include "dsp/statistics_functions.h" +#include "dsp/basic_math_functions.h" +#include "dsp/complex_math_functions.h" +#include "dsp/fast_math_functions.h" +#include "dsp/matrix_functions.h" + +/* Constants for Q31 implementation */ +#define LOG2TOLOG_Q31 0x02C5C860 +#define MICRO_Q31 0x08637BD0 +#define SHIFT_MELFILTER_SATURATION_Q31 10 +/** + @ingroup MFCC + */ + + + +/** + @addtogroup MFCCQ31 + @{ + */ + +/** + @brief MFCC Q31 + @param[in] S points to the mfcc instance structure + @param[in] pSrc points to the input samples in Q31 + @param[out] pDst points to the output MFCC values in q8.23 format + @param[inout] pTmp points to a temporary buffer of complex + @return error status + + @par Description + The number of input samples is the FFT length used + when initializing the instance data structure. + + The source buffer is modified by this function. + + The function may saturate. If the FFT length is too + big and the number of MEL filters too small then the fixed + point computations may saturate. + + @par Neon implementation + There is an additional temporary buffer used for the RFFT. + + + @code + arm_status arm_mfcc_q31( + const arm_mfcc_instance_q31 * S, + q31_t *pSrc, + q31_t *pDst, + q31_t *pTmp, + q31_t *pTmp_rfft + ) + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + + */ +#if defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_q31( + const arm_mfcc_instance_q31 * S, + q31_t *pSrc, + q31_t *pDst, + q31_t *pTmp, + q31_t *pTmp_rfft + ) +#else +ARM_DSP_ATTRIBUTE arm_status arm_mfcc_q31( + const arm_mfcc_instance_q31 * S, + q31_t *pSrc, + q31_t *pDst, + q31_t *pTmp + ) +#endif +{ + q31_t m; + uint32_t index; + uint32_t fftShift=0; + q31_t logExponent; + q63_t result; + arm_matrix_instance_q31 pDctMat; + uint32_t i; + uint32_t coefsPos; + uint32_t filterLimit; + q31_t *pTmp2=(q31_t*)pTmp; + + arm_status status = ARM_MATH_SUCCESS; + + // q31 + arm_absmax_q31(pSrc,S->fftLen,&m,&index); + + if ((m != 0) && (m != 0x7FFFFFFF)) + { + q31_t quotient; + int16_t shift; + + status = arm_divide_q31(0x7FFFFFFF,m,"ient,&shift); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + + arm_scale_q31(pSrc,quotient,shift,pSrc,S->fftLen); + } + + + // q31 + arm_mult_q31(pSrc,S->windowCoefs, pSrc, S->fftLen); + + + /* Compute spectrum magnitude + */ + fftShift = 31 - __CLZ(S->fftLen); +#if defined(ARM_MATH_NEON) + /* Default RFFT based implementation */ + arm_rfft_q31(&(S->rfft),pSrc,pTmp2,pTmp_rfft,0); +#else +#if defined(ARM_MFCC_USE_CFFT) + /* some HW accelerator for CMSIS-DSP used in some boards + are only providing acceleration for CFFT. + With ARM_MFCC_USE_CFFT enabled, CFFT is used and the MFCC + will be accelerated on those boards. + + The default is to use RFFT + */ + /* Convert from real to complex */ + for(i=0; i < S->fftLen ; i++) + { + pTmp2[2*i] = pSrc[i]; + pTmp2[2*i+1] = 0; + } + arm_cfft_q31(&(S->cfft),pTmp2,0,1); +#else + /* Default RFFT based implementation */ + arm_rfft_q31(&(S->rfft),pSrc,pTmp2); +#endif +#endif + filterLimit = 1 + (S->fftLen >> 1); + + + // q31 - fftShift + arm_cmplx_mag_q31(pTmp2,pSrc,filterLimit); + // q30 - fftShift + + + /* Apply MEL filters */ + coefsPos = 0; + for(i=0; i<S->nbMelFilters; i++) + { + arm_dot_prod_q31(pSrc+S->filterPos[i], + &(S->filterCoefs[coefsPos]), + S->filterLengths[i], + &result); + + + coefsPos += S->filterLengths[i]; + + // q16.48 - fftShift + result += MICRO_Q31; + result >>= (SHIFT_MELFILTER_SATURATION_Q31 + 18); + // q16.29 - fftShift - satShift + pTmp[i] = __SSAT(result,31) ; + + } + + if ((m != 0) && (m != 0x7FFFFFFF)) + { + arm_scale_q31(pTmp,m,0,pTmp,S->nbMelFilters); + } + + // q16.29 - fftShift - satShift + /* Compute the log */ + arm_vlog_q31(pTmp,pTmp,S->nbMelFilters); + + + // q5.26 + + logExponent = fftShift + 2 + SHIFT_MELFILTER_SATURATION_Q31; + logExponent = logExponent * LOG2TOLOG_Q31; + + + // q5.26 + arm_offset_q31(pTmp,logExponent,pTmp,S->nbMelFilters); + arm_shift_q31(pTmp,-3,pTmp,S->nbMelFilters); + + + // q8.23 + + pDctMat.numRows=S->nbDctOutputs; + pDctMat.numCols=S->nbMelFilters; + pDctMat.pData=(q31_t*)S->dctCoefs; + + arm_mat_vec_mult_q31(&pDctMat, pTmp, pDst); + + return(status); +} + +/** + @} end of MFCCQ31 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f16.c new file mode 100755 index 0000000..f39f844 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f16.c @@ -0,0 +1,556 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_fast_f16.c + * Description: RFFT & RIFFT Floating point process function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" +#include "arm_common_tables_f16.h" + +#if defined(ARM_FLOAT16_SUPPORTED) + + +#if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE) + +static void stage_rfft_f16( + const arm_rfft_fast_instance_f16 * S, + const float16_t * p, + float16_t * pOut) +{ + int32_t k; /* Loop Counter */ + float16_t twR, twI; /* RFFT Twiddle coefficients */ + const float16_t * pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float16_t *pA = p; /* increasing pointer */ + const float16_t *pB = p; /* decreasing pointer */ + float16_t xAR, xAI, xBR, xBI; /* temporary variables */ + float16_t t1a, t1b; /* temporary variables */ + float16_t p0, p1, p2, p3; /* temporary variables */ + + float16x8x2_t tw,xA,xB; + float16x8x2_t tmp1, tmp2, res; + + uint16x8_t vecStridesBkwd; + + vecStridesBkwd = vddupq_u16((uint16_t)14, 2); + + + int blockCnt; + + + k = (S->Sint).fftLen - 1; + + /* Pack first and last sample of the frequency domain together */ + + xBR = pB[0]; + xBI = pB[1]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++ ; + twI = *pCoeff++ ; + + // U1 = XA(1) + XB(1); % It is real + t1a = (_Float16)xBR + (_Float16)xAR ; + + // U2 = XB(1) - XA(1); % It is imaginary + t1b = (_Float16)xBI + (_Float16)xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + *pOut++ = 0.5f16 * ( (_Float16)t1a + (_Float16)t1b ); + *pOut++ = 0.5f16 * ( (_Float16)t1a - (_Float16)t1b ); + + // XA(1) = 1/2*( U1 - imag(U2) + i*( U1 +imag(U2) )); + pB = p + 2*k - 14; + pA += 2; + + blockCnt = k >> 3; + while (blockCnt > 0) + { + /* + function X = my_split_rfft(X, ifftFlag) + % X is a series of real numbers + L = length(X); + XC = X(1:2:end) +i*X(2:2:end); + XA = fft(XC); + XB = conj(XA([1 end:-1:2])); + TW = i*exp(-2*pi*i*[0:L/2-1]/L).'; + for l = 2:L/2 + XA(l) = 1/2 * (XA(l) + XB(l) + TW(l) * (XB(l) - XA(l))); + end + XA(1) = 1/2* (XA(1) + XB(1) + TW(1) * (XB(1) - XA(1))) + i*( 1/2*( XA(1) + XB(1) + i*( XA(1) - XB(1)))); + X = XA; + */ + + + xA = vld2q_f16(pA); + pA += 16; + + xB = vld2q_f16(pB); + + xB.val[0] = vldrhq_gather_shifted_offset_f16(pB, vecStridesBkwd); + xB.val[1] = vldrhq_gather_shifted_offset_f16(&pB[1], vecStridesBkwd); + + xB.val[1] = vnegq_f16(xB.val[1]); + pB -= 16; + + + tw = vld2q_f16(pCoeff); + pCoeff += 16; + + + tmp1.val[0] = vaddq_f16(xA.val[0],xB.val[0]); + tmp1.val[1] = vaddq_f16(xA.val[1],xB.val[1]); + + tmp2.val[0] = vsubq_f16(xB.val[0],xA.val[0]); + tmp2.val[1] = vsubq_f16(xB.val[1],xA.val[1]); + + res.val[0] = vmulq(tw.val[0], tmp2.val[0]); + res.val[0] = vfmsq(res.val[0],tw.val[1], tmp2.val[1]); + + res.val[1] = vmulq(tw.val[0], tmp2.val[1]); + res.val[1] = vfmaq(res.val[1], tw.val[1], tmp2.val[0]); + + res.val[0] = vaddq_f16(res.val[0],tmp1.val[0] ); + res.val[1] = vaddq_f16(res.val[1],tmp1.val[1] ); + + res.val[0] = vmulq_n_f16(res.val[0], 0.5f); + res.val[1] = vmulq_n_f16(res.val[1], 0.5f); + + + vst2q_f16(pOut, res); + pOut += 16; + + + blockCnt--; + } + + pB += 14; + blockCnt = k & 7; + while (blockCnt > 0) + { + /* + function X = my_split_rfft(X, ifftFlag) + % X is a series of real numbers + L = length(X); + XC = X(1:2:end) +i*X(2:2:end); + XA = fft(XC); + XB = conj(XA([1 end:-1:2])); + TW = i*exp(-2*pi*i*[0:L/2-1]/L).'; + for l = 2:L/2 + XA(l) = 1/2 * (XA(l) + XB(l) + TW(l) * (XB(l) - XA(l))); + end + XA(1) = 1/2* (XA(1) + XB(1) + TW(1) * (XB(1) - XA(1))) + i*( 1/2*( XA(1) + XB(1) + i*( XA(1) - XB(1)))); + X = XA; + */ + + xBI = pB[1]; + xBR = pB[0]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = (_Float16)xBR - (_Float16)xAR ; + t1b = (_Float16)xBI + (_Float16)xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + p0 = (_Float16)twR * (_Float16)t1a; + p1 = (_Float16)twI * (_Float16)t1a; + p2 = (_Float16)twR * (_Float16)t1b; + p3 = (_Float16)twI * (_Float16)t1b; + + *pOut++ = 0.5f16 * ((_Float16)xAR + (_Float16)xBR + (_Float16)p0 + (_Float16)p3 ); //xAR + *pOut++ = 0.5f16 * ((_Float16)xAI - (_Float16)xBI + (_Float16)p1 - (_Float16)p2 ); //xAI + + pA += 2; + pB -= 2; + blockCnt--; + } +} + +/* Prepares data for inverse cfft */ +static void merge_rfft_f16( + const arm_rfft_fast_instance_f16 * S, + const float16_t * p, + float16_t * pOut) +{ + int32_t k; /* Loop Counter */ + float16_t twR, twI; /* RFFT Twiddle coefficients */ + const float16_t *pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float16_t *pA = p; /* increasing pointer */ + const float16_t *pB = p; /* decreasing pointer */ + float16_t xAR, xAI, xBR, xBI; /* temporary variables */ + float16_t t1a, t1b, r, s, t, u; /* temporary variables */ + + float16x8x2_t tw,xA,xB; + float16x8x2_t tmp1, tmp2, res; + uint16x8_t vecStridesBkwd; + + vecStridesBkwd = vddupq_u16((uint16_t)14, 2); + + int blockCnt; + + + k = (S->Sint).fftLen - 1; + + xAR = pA[0]; + xAI = pA[1]; + + pCoeff += 2 ; + + *pOut++ = 0.5f16 * ( (_Float16)xAR + (_Float16)xAI ); + *pOut++ = 0.5f16 * ( (_Float16)xAR - (_Float16)xAI ); + + pB = p + 2*k - 14; + pA += 2 ; + + blockCnt = k >> 3; + while (blockCnt > 0) + { + /* G is half of the frequency complex spectrum */ + //for k = 2:N + // Xk(k) = 1/2 * (G(k) + conj(G(N-k+2)) + Tw(k)*( G(k) - conj(G(N-k+2)))); + xA = vld2q_f16(pA); + pA += 16; + + xB = vld2q_f16(pB); + + xB.val[0] = vldrhq_gather_shifted_offset_f16(pB, vecStridesBkwd); + xB.val[1] = vldrhq_gather_shifted_offset_f16(&pB[1], vecStridesBkwd); + + xB.val[1] = vnegq_f16(xB.val[1]); + pB -= 16; + + + tw = vld2q_f16(pCoeff); + tw.val[1] = vnegq_f16(tw.val[1]); + pCoeff += 16; + + + tmp1.val[0] = vaddq_f16(xA.val[0],xB.val[0]); + tmp1.val[1] = vaddq_f16(xA.val[1],xB.val[1]); + + tmp2.val[0] = vsubq_f16(xB.val[0],xA.val[0]); + tmp2.val[1] = vsubq_f16(xB.val[1],xA.val[1]); + + res.val[0] = vmulq(tw.val[0], tmp2.val[0]); + res.val[0] = vfmsq(res.val[0],tw.val[1], tmp2.val[1]); + + res.val[1] = vmulq(tw.val[0], tmp2.val[1]); + res.val[1] = vfmaq(res.val[1], tw.val[1], tmp2.val[0]); + + res.val[0] = vaddq_f16(res.val[0],tmp1.val[0] ); + res.val[1] = vaddq_f16(res.val[1],tmp1.val[1] ); + + res.val[0] = vmulq_n_f16(res.val[0], 0.5f); + res.val[1] = vmulq_n_f16(res.val[1], 0.5f); + + + vst2q_f16(pOut, res); + pOut += 16; + + + blockCnt--; + } + + pB += 14; + blockCnt = k & 7; + while (blockCnt > 0) + { + /* G is half of the frequency complex spectrum */ + //for k = 2:N + // Xk(k) = 1/2 * (G(k) + conj(G(N-k+2)) + Tw(k)*( G(k) - conj(G(N-k+2)))); + xBI = pB[1] ; + xBR = pB[0] ; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = (_Float16)xAR - (_Float16)xBR ; + t1b = (_Float16)xAI + (_Float16)xBI ; + + r = (_Float16)twR * (_Float16)t1a; + s = (_Float16)twI * (_Float16)t1b; + t = (_Float16)twI * (_Float16)t1a; + u = (_Float16)twR * (_Float16)t1b; + + // real(tw * (xA - xB)) = twR * (xAR - xBR) - twI * (xAI - xBI); + // imag(tw * (xA - xB)) = twI * (xAR - xBR) + twR * (xAI - xBI); + *pOut++ = 0.5f16 * ((_Float16)xAR + (_Float16)xBR - (_Float16)r - (_Float16)s ); //xAR + *pOut++ = 0.5f16 * ((_Float16)xAI - (_Float16)xBI + (_Float16)t - (_Float16)u ); //xAI + + pA += 2; + pB -= 2; + blockCnt--; + } + +} +#elif defined(ARM_MATH_NEON_FLOAT16) +/* + +No stage merge functions defined here for Neon. + +*/ +#else +static void stage_rfft_f16( + const arm_rfft_fast_instance_f16 * S, + const float16_t * p, + float16_t * pOut) +{ + int32_t k; /* Loop Counter */ + float16_t twR, twI; /* RFFT Twiddle coefficients */ + const float16_t * pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float16_t *pA = p; /* increasing pointer */ + const float16_t *pB = p; /* decreasing pointer */ + float16_t xAR, xAI, xBR, xBI; /* temporary variables */ + float16_t t1a, t1b; /* temporary variables */ + float16_t p0, p1, p2, p3; /* temporary variables */ + + + k = (S->Sint).fftLen - 1; + + /* Pack first and last sample of the frequency domain together */ + + xBR = pB[0]; + xBI = pB[1]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++ ; + twI = *pCoeff++ ; + + + // U1 = XA(1) + XB(1); % It is real + t1a = (_Float16)xBR + (_Float16)xAR ; + + // U2 = XB(1) - XA(1); % It is imaginary + t1b = (_Float16)xBI + (_Float16)xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + *pOut++ = 0.5f16 * ( (_Float16)t1a + (_Float16)t1b ); + *pOut++ = 0.5f16 * ( (_Float16)t1a - (_Float16)t1b ); + + // XA(1) = 1/2*( U1 - imag(U2) + i*( U1 +imag(U2) )); + pB = p + 2*k; + pA += 2; + + do + { + /* + function X = my_split_rfft(X, ifftFlag) + % X is a series of real numbers + L = length(X); + XC = X(1:2:end) +i*X(2:2:end); + XA = fft(XC); + XB = conj(XA([1 end:-1:2])); + TW = i*exp(-2*pi*i*[0:L/2-1]/L).'; + for l = 2:L/2 + XA(l) = 1/2 * (XA(l) + XB(l) + TW(l) * (XB(l) - XA(l))); + end + XA(1) = 1/2* (XA(1) + XB(1) + TW(1) * (XB(1) - XA(1))) + i*( 1/2*( XA(1) + XB(1) + i*( XA(1) - XB(1)))); + X = XA; + */ + + xBI = pB[1]; + xBR = pB[0]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = (_Float16)xBR - (_Float16)xAR ; + t1b = (_Float16)xBI + (_Float16)xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + p0 = (_Float16)twR * (_Float16)t1a; + p1 = (_Float16)twI * (_Float16)t1a; + p2 = (_Float16)twR * (_Float16)t1b; + p3 = (_Float16)twI * (_Float16)t1b; + + *pOut++ = 0.5f16 * ((_Float16)xAR + (_Float16)xBR + (_Float16)p0 + (_Float16)p3 ); //xAR + *pOut++ = 0.5f16 * ((_Float16)xAI - (_Float16)xBI + (_Float16)p1 - (_Float16)p2 ); //xAI + + + pA += 2; + pB -= 2; + k--; + } while (k > 0); +} + +/* Prepares data for inverse cfft */ +static void merge_rfft_f16( + const arm_rfft_fast_instance_f16 * S, + const float16_t * p, + float16_t * pOut) +{ + int32_t k; /* Loop Counter */ + float16_t twR, twI; /* RFFT Twiddle coefficients */ + const float16_t *pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float16_t *pA = p; /* increasing pointer */ + const float16_t *pB = p; /* decreasing pointer */ + float16_t xAR, xAI, xBR, xBI; /* temporary variables */ + float16_t t1a, t1b, r, s, t, u; /* temporary variables */ + + k = (S->Sint).fftLen - 1; + + xAR = pA[0]; + xAI = pA[1]; + + pCoeff += 2 ; + + *pOut++ = 0.5f16 * ( (_Float16)xAR + (_Float16)xAI ); + *pOut++ = 0.5f16 * ( (_Float16)xAR - (_Float16)xAI ); + + pB = p + 2*k ; + pA += 2 ; + + while (k > 0) + { + /* G is half of the frequency complex spectrum */ + //for k = 2:N + // Xk(k) = 1/2 * (G(k) + conj(G(N-k+2)) + Tw(k)*( G(k) - conj(G(N-k+2)))); + xBI = pB[1] ; + xBR = pB[0] ; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = (_Float16)xAR - (_Float16)xBR ; + t1b = (_Float16)xAI + (_Float16)xBI ; + + r = (_Float16)twR * (_Float16)t1a; + s = (_Float16)twI * (_Float16)t1b; + t = (_Float16)twI * (_Float16)t1a; + u = (_Float16)twR * (_Float16)t1b; + + // real(tw * (xA - xB)) = twR * (xAR - xBR) - twI * (xAI - xBI); + // imag(tw * (xA - xB)) = twI * (xAR - xBR) + twR * (xAI - xBI); + *pOut++ = 0.5f16 * ((_Float16)xAR + (_Float16)xBR - (_Float16)r - (_Float16)s ); //xAR + *pOut++ = 0.5f16 * ((_Float16)xAI - (_Float16)xBI + (_Float16)t - (_Float16)u ); //xAI + + pA += 2; + pB -= 2; + k--; + } + +} + +#endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */ + +/** + @ingroup RealFFT +*/ + +/** + @defgroup RealFFTF16 Real FFT F16 Functions +*/ + +/** + @addtogroup RealFFTF16 + @{ +*/ + +/** + @brief Processing function for the floating-point real FFT. + @param[in] S points to an arm_rfft_fast_instance_f16 structure + @param[in] p points to input buffer (Source buffer is modified by this function.) + @param[in] pOut points to output buffer + @param[in] ifftFlag + - value = 0: RFFT + - value = 1: RIFFT + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". +*/ +#if defined(ARM_MATH_NEON_FLOAT16) + +#include "CMSIS_NE10_types.h" +#include "CMSIS_NE10_fft.h" + +ARM_DSP_ATTRIBUTE void arm_rfft_fast_f16( + const arm_rfft_fast_instance_f16 * S, + const float16_t * p, + float16_t * pOut, + float16_t *tmpbuf, + uint8_t ifftFlag) +{ +/* Calculation of Real FFT */ + if (!ifftFlag) + { + arm_ne10_fft_r2c_1d_float16_neon (S,p,pOut,tmpbuf); + } + else + { + arm_ne10_fft_c2r_1d_float16_neon (S,p,pOut,tmpbuf); + } +} + +#else +ARM_DSP_ATTRIBUTE void arm_rfft_fast_f16( + const arm_rfft_fast_instance_f16 * S, + float16_t * p, + float16_t * pOut, + uint8_t ifftFlag) +{ + const arm_cfft_instance_f16 * Sint = &(S->Sint); + + + /* Calculation of Real FFT */ + if (ifftFlag) + { + /* Real FFT compression */ + merge_rfft_f16(S, p, pOut); + /* Complex radix-4 IFFT process */ + arm_cfft_f16( Sint, pOut, ifftFlag, 1); + } + else + { + + /* Calculation of RFFT of input */ + arm_cfft_f16( Sint, p, ifftFlag, 1); + + /* Real FFT extraction */ + stage_rfft_f16(S, p, pOut); + } +} +#endif +/** +* @} end of RealFFTF16 group +*/ + +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f32.c new file mode 100755 index 0000000..7e6b029 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f32.c @@ -0,0 +1,706 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_fast_f32.c + * Description: RFFT & RIFFT Floating point process function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) +static void stage_rfft_f32( + const arm_rfft_fast_instance_f32 * S, + const float32_t * p, + float32_t * pOut) +{ + int32_t k; /* Loop Counter */ + float32_t twR, twI; /* RFFT Twiddle coefficients */ + const float32_t * pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float32_t *pA = p; /* increasing pointer */ + const float32_t *pB = p; /* decreasing pointer */ + float32_t xAR, xAI, xBR, xBI; /* temporary variables */ + float32_t t1a, t1b; /* temporary variables */ + float32_t p0, p1, p2, p3; /* temporary variables */ + + float32x4x2_t tw,xA,xB; + float32x4x2_t tmp1, tmp2, res; + + uint32x4_t vecStridesFwd, vecStridesBkwd; + + vecStridesFwd = vidupq_u32((uint32_t)0, 2); + vecStridesBkwd = -vecStridesFwd; + + int blockCnt; + + + k = (S->Sint).fftLen - 1; + + /* Pack first and last sample of the frequency domain together */ + + xBR = pB[0]; + xBI = pB[1]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++ ; + twI = *pCoeff++ ; + + // U1 = XA(1) + XB(1); % It is real + t1a = xBR + xAR ; + + // U2 = XB(1) - XA(1); % It is imaginary + t1b = xBI + xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + *pOut++ = 0.5f * ( t1a + t1b ); + *pOut++ = 0.5f * ( t1a - t1b ); + + // XA(1) = 1/2*( U1 - imag(U2) + i*( U1 +imag(U2) )); + pB = p + 2*k; + pA += 2; + + blockCnt = k >> 2; + while (blockCnt > 0) + { + /* + function X = my_split_rfft(X, ifftFlag) + % X is a series of real numbers + L = length(X); + XC = X(1:2:end) +i*X(2:2:end); + XA = fft(XC); + XB = conj(XA([1 end:-1:2])); + TW = i*exp(-2*pi*i*[0:L/2-1]/L).'; + for l = 2:L/2 + XA(l) = 1/2 * (XA(l) + XB(l) + TW(l) * (XB(l) - XA(l))); + end + XA(1) = 1/2* (XA(1) + XB(1) + TW(1) * (XB(1) - XA(1))) + i*( 1/2*( XA(1) + XB(1) + i*( XA(1) - XB(1)))); + X = XA; + */ + + + xA = vld2q_f32(pA); + pA += 8; + + xB = vld2q_f32(pB); + + xB.val[0] = vldrwq_gather_shifted_offset_f32(pB, vecStridesBkwd); + xB.val[1] = vldrwq_gather_shifted_offset_f32(&pB[1], vecStridesBkwd); + + xB.val[1] = vnegq_f32(xB.val[1]); + pB -= 8; + + + tw = vld2q_f32(pCoeff); + pCoeff += 8; + + + tmp1.val[0] = vaddq_f32(xA.val[0],xB.val[0]); + tmp1.val[1] = vaddq_f32(xA.val[1],xB.val[1]); + + tmp2.val[0] = vsubq_f32(xB.val[0],xA.val[0]); + tmp2.val[1] = vsubq_f32(xB.val[1],xA.val[1]); + + res.val[0] = vmulq(tw.val[0], tmp2.val[0]); + res.val[0] = vfmsq(res.val[0],tw.val[1], tmp2.val[1]); + + res.val[1] = vmulq(tw.val[0], tmp2.val[1]); + res.val[1] = vfmaq(res.val[1], tw.val[1], tmp2.val[0]); + + res.val[0] = vaddq_f32(res.val[0],tmp1.val[0] ); + res.val[1] = vaddq_f32(res.val[1],tmp1.val[1] ); + + res.val[0] = vmulq_n_f32(res.val[0], 0.5f); + res.val[1] = vmulq_n_f32(res.val[1], 0.5f); + + + vst2q_f32(pOut, res); + pOut += 8; + + + blockCnt--; + } + + blockCnt = k & 3; + while (blockCnt > 0) + { + /* + function X = my_split_rfft(X, ifftFlag) + % X is a series of real numbers + L = length(X); + XC = X(1:2:end) +i*X(2:2:end); + XA = fft(XC); + XB = conj(XA([1 end:-1:2])); + TW = i*exp(-2*pi*i*[0:L/2-1]/L).'; + for l = 2:L/2 + XA(l) = 1/2 * (XA(l) + XB(l) + TW(l) * (XB(l) - XA(l))); + end + XA(1) = 1/2* (XA(1) + XB(1) + TW(1) * (XB(1) - XA(1))) + i*( 1/2*( XA(1) + XB(1) + i*( XA(1) - XB(1)))); + X = XA; + */ + + xBI = pB[1]; + xBR = pB[0]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = xBR - xAR ; + t1b = xBI + xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + p0 = twR * t1a; + p1 = twI * t1a; + p2 = twR * t1b; + p3 = twI * t1b; + + *pOut++ = 0.5f * (xAR + xBR + p0 + p3 ); //xAR + *pOut++ = 0.5f * (xAI - xBI + p1 - p2 ); //xAI + + pA += 2; + pB -= 2; + blockCnt--; + } +} + +/* Prepares data for inverse cfft */ +static void merge_rfft_f32( + const arm_rfft_fast_instance_f32 * S, + const float32_t * p, + float32_t * pOut) +{ + int32_t k; /* Loop Counter */ + float32_t twR, twI; /* RFFT Twiddle coefficients */ + const float32_t *pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float32_t *pA = p; /* increasing pointer */ + const float32_t *pB = p; /* decreasing pointer */ + float32_t xAR, xAI, xBR, xBI; /* temporary variables */ + float32_t t1a, t1b, r, s, t, u; /* temporary variables */ + + float32x4x2_t tw,xA,xB; + float32x4x2_t tmp1, tmp2, res; + uint32x4_t vecStridesFwd, vecStridesBkwd; + + vecStridesFwd = vidupq_u32((uint32_t)0, 2); + vecStridesBkwd = -vecStridesFwd; + + int blockCnt; + + + k = (S->Sint).fftLen - 1; + + xAR = pA[0]; + xAI = pA[1]; + + pCoeff += 2 ; + + *pOut++ = 0.5f * ( xAR + xAI ); + *pOut++ = 0.5f * ( xAR - xAI ); + + pB = p + 2*k ; + pA += 2 ; + + blockCnt = k >> 2; + while (blockCnt > 0) + { + /* G is half of the frequency complex spectrum */ + //for k = 2:N + // Xk(k) = 1/2 * (G(k) + conj(G(N-k+2)) + Tw(k)*( G(k) - conj(G(N-k+2)))); + xA = vld2q_f32(pA); + pA += 8; + + xB = vld2q_f32(pB); + + xB.val[0] = vldrwq_gather_shifted_offset_f32(pB, vecStridesBkwd); + xB.val[1] = vldrwq_gather_shifted_offset_f32(&pB[1], vecStridesBkwd); + + xB.val[1] = vnegq_f32(xB.val[1]); + pB -= 8; + + + tw = vld2q_f32(pCoeff); + tw.val[1] = vnegq_f32(tw.val[1]); + pCoeff += 8; + + + tmp1.val[0] = vaddq_f32(xA.val[0],xB.val[0]); + tmp1.val[1] = vaddq_f32(xA.val[1],xB.val[1]); + + tmp2.val[0] = vsubq_f32(xB.val[0],xA.val[0]); + tmp2.val[1] = vsubq_f32(xB.val[1],xA.val[1]); + + res.val[0] = vmulq(tw.val[0], tmp2.val[0]); + res.val[0] = vfmsq(res.val[0],tw.val[1], tmp2.val[1]); + + res.val[1] = vmulq(tw.val[0], tmp2.val[1]); + res.val[1] = vfmaq(res.val[1], tw.val[1], tmp2.val[0]); + + res.val[0] = vaddq_f32(res.val[0],tmp1.val[0] ); + res.val[1] = vaddq_f32(res.val[1],tmp1.val[1] ); + + res.val[0] = vmulq_n_f32(res.val[0], 0.5f); + res.val[1] = vmulq_n_f32(res.val[1], 0.5f); + + + vst2q_f32(pOut, res); + pOut += 8; + + + blockCnt--; + } + + blockCnt = k & 3; + while (blockCnt > 0) + { + /* G is half of the frequency complex spectrum */ + //for k = 2:N + // Xk(k) = 1/2 * (G(k) + conj(G(N-k+2)) + Tw(k)*( G(k) - conj(G(N-k+2)))); + xBI = pB[1] ; + xBR = pB[0] ; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = xAR - xBR ; + t1b = xAI + xBI ; + + r = twR * t1a; + s = twI * t1b; + t = twI * t1a; + u = twR * t1b; + + // real(tw * (xA - xB)) = twR * (xAR - xBR) - twI * (xAI - xBI); + // imag(tw * (xA - xB)) = twI * (xAR - xBR) + twR * (xAI - xBI); + *pOut++ = 0.5f * (xAR + xBR - r - s ); //xAR + *pOut++ = 0.5f * (xAI - xBI + t - u ); //xAI + + pA += 2; + pB -= 2; + blockCnt--; + } + +} +#elif defined(ARM_MATH_NEON) +/* + +No stage merge functions defined here for Neon. + +*/ +#else +static void stage_rfft_f32( + const arm_rfft_fast_instance_f32 * S, + const float32_t * p, + float32_t * pOut) +{ + int32_t k; /* Loop Counter */ + float32_t twR, twI; /* RFFT Twiddle coefficients */ + const float32_t * pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float32_t *pA = p; /* increasing pointer */ + const float32_t *pB = p; /* decreasing pointer */ + float32_t xAR, xAI, xBR, xBI; /* temporary variables */ + float32_t t1a, t1b; /* temporary variables */ + float32_t p0, p1, p2, p3; /* temporary variables */ + + + k = (S->Sint).fftLen - 1; + + /* Pack first and last sample of the frequency domain together */ + + xBR = pB[0]; + xBI = pB[1]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++ ; + twI = *pCoeff++ ; + + + // U1 = XA(1) + XB(1); % It is real + t1a = xBR + xAR ; + + // U2 = XB(1) - XA(1); % It is imaginary + t1b = xBI + xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + *pOut++ = 0.5f * ( t1a + t1b ); + *pOut++ = 0.5f * ( t1a - t1b ); + + // XA(1) = 1/2*( U1 - imag(U2) + i*( U1 +imag(U2) )); + pB = p + 2*k; + pA += 2; + + do + { + /* + function X = my_split_rfft(X, ifftFlag) + % X is a series of real numbers + L = length(X); + XC = X(1:2:end) +i*X(2:2:end); + XA = fft(XC); + XB = conj(XA([1 end:-1:2])); + TW = i*exp(-2*pi*i*[0:L/2-1]/L).'; + for l = 2:L/2 + XA(l) = 1/2 * (XA(l) + XB(l) + TW(l) * (XB(l) - XA(l))); + end + XA(1) = 1/2* (XA(1) + XB(1) + TW(1) * (XB(1) - XA(1))) + i*( 1/2*( XA(1) + XB(1) + i*( XA(1) - XB(1)))); + X = XA; + */ + + xBI = pB[1]; + xBR = pB[0]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = xBR - xAR ; + t1b = xBI + xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + p0 = twR * t1a; + p1 = twI * t1a; + p2 = twR * t1b; + p3 = twI * t1b; + + *pOut++ = 0.5f * (xAR + xBR + p0 + p3 ); //xAR + *pOut++ = 0.5f * (xAI - xBI + p1 - p2 ); //xAI + + + pA += 2; + pB -= 2; + k--; + } while (k > 0); +} + +/* Prepares data for inverse cfft */ +static void merge_rfft_f32( + const arm_rfft_fast_instance_f32 * S, + const float32_t * p, + float32_t * pOut) +{ + int32_t k; /* Loop Counter */ + float32_t twR, twI; /* RFFT Twiddle coefficients */ + const float32_t *pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float32_t *pA = p; /* increasing pointer */ + const float32_t *pB = p; /* decreasing pointer */ + float32_t xAR, xAI, xBR, xBI; /* temporary variables */ + float32_t t1a, t1b, r, s, t, u; /* temporary variables */ + + k = (S->Sint).fftLen - 1; + + xAR = pA[0]; + xAI = pA[1]; + + pCoeff += 2 ; + + *pOut++ = 0.5f * ( xAR + xAI ); + *pOut++ = 0.5f * ( xAR - xAI ); + + pB = p + 2*k ; + pA += 2 ; + + while (k > 0) + { + /* G is half of the frequency complex spectrum */ + //for k = 2:N + // Xk(k) = 1/2 * (G(k) + conj(G(N-k+2)) + Tw(k)*( G(k) - conj(G(N-k+2)))); + xBI = pB[1] ; + xBR = pB[0] ; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = xAR - xBR ; + t1b = xAI + xBI ; + + r = twR * t1a; + s = twI * t1b; + t = twI * t1a; + u = twR * t1b; + + // real(tw * (xA - xB)) = twR * (xAR - xBR) - twI * (xAI - xBI); + // imag(tw * (xA - xB)) = twI * (xAR - xBR) + twR * (xAI - xBI); + *pOut++ = 0.5f * (xAR + xBR - r - s ); //xAR + *pOut++ = 0.5f * (xAI - xBI + t - u ); //xAI + + pA += 2; + pB -= 2; + k--; + } + +} + +#endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */ + +/** + @ingroup groupTransforms +*/ + +/** + @defgroup RealFFT Real FFT Functions + + @par + The CMSIS DSP library includes specialized algorithms for computing the + FFT of real data sequences. The FFT is defined over complex data but + in many applications the input is real. Real FFT algorithms take advantage + of the symmetry properties of the FFT and have a speed advantage over complex + algorithms of the same length. + @par + The Fast RFFT algorithm relays on the mixed radix CFFT that save processor usage. + @par + The real length N forward FFT of a sequence is computed using the steps shown below. + @par + \image html RFFT.gif "Real Fast Fourier Transform" + @par + The real sequence is initially treated as if it were complex to perform a CFFT. + Later, a processing stage reshapes the data to obtain half of the frequency spectrum + in complex format. + + @par + The input for the inverse RFFT should keep the same format as the output of the + forward RFFT. A first processing stage pre-process the data to later perform an + inverse CFFT. + @par + \image html RIFFT.gif "Real Inverse Fast Fourier Transform" + @par + The algorithms for floating-point, Q15, and Q31 data are slightly different + and we describe each algorithm in turn. + @par Floating-point + The main functions are \ref arm_rfft_fast_f32() and \ref arm_rfft_fast_init_f32(). + + For f16, the functions are \ref arm_rfft_fast_f16() and \ref arm_rfft_fast_init_f16(). + For f64, the functions are \ref arm_rfft_fast_f64() and \ref arm_rfft_fast_init_f64(). + @par + The FFT of a real N-point sequence has even symmetry in the frequency domain. + The second half of the data equals the conjugate of the first half flipped in frequency. + This conjugate part is not computed by the float RFFT. As consequence, the output of + a N point real FFT should be a N//2 + 1 complex numbers so N + 2 floats. + @par + It happens that the first complex of number of the RFFT output is actually + all real. Its real part represents the DC offset. + The value at Nyquist frequency is also real. + + @par + Those two complex numbers can be encoded with 2 floats rather than using two numbers + with an imaginary part set to zero. + @par + The implementation is using a trick so that the output buffer can be N float : + the last real is packaged in the imaginary part of the first complex (since + this imaginary part is not used and is zero). + + @par + The real FFT functions pack the frequency domain data in this fashion. + The forward transform outputs the data in this form and the inverse + transform expects input data in this form. The function always performs + the needed bitreversal so that the input and output data is always in + normal order. The functions support lengths of [32, 64, 128, ..., 4096] + samples. + @par Q15 and Q31 + The real algorithms are defined in a similar manner and utilize N/2 complex + transforms behind the scenes. + + @par + But warning, contrary to the float version, the fixed point implementation + RFFT is also computing the conjugate part (except for MVE version) so the + output buffer must be bigger. + Also the fixed point RFFTs are not using any trick to pack the DC and Nyquist + frequency in the same complex number. + The RIFFT is not using the conjugate part but it is still using the Nyquist + frequency value. The details are given in the documentation for the functions. + @par + The complex transforms used internally include scaling to prevent fixed-point + overflows. The overall scaling equals 1/(fftLen/2). + Due to the use of complex transform internally, the source buffer is + modified by the rfft. + @par + A separate instance structure must be defined for each transform used but + twiddle factor and bit reversal tables can be reused. + @par + There is also an associated initialization function for each data type. + The initialization function performs the following operations: + - Sets the values of the internal structure fields. + - Initializes twiddle factor table and bit reversal table pointers. + - Initializes the internal complex FFT data structure. + @par + Use of the initialization function is optional **except for MVE versions where it is mandatory**. + If you don't use the initialization functions, then the structures should be initialized with code + similar to the one below: + <pre> + arm_rfft_instance_q31 S = {fftLenReal, fftLenBy2, ifftFlagR, bitReverseFlagR, twidCoefRModifier, pTwiddleAReal, pTwiddleBReal, pCfft}; + arm_rfft_instance_q15 S = {fftLenReal, fftLenBy2, ifftFlagR, bitReverseFlagR, twidCoefRModifier, pTwiddleAReal, pTwiddleBReal, pCfft}; + </pre> + where <code>fftLenReal</code> is the length of the real transform; + <code>fftLenBy2</code> length of the internal complex transform (fftLenReal/2). + <code>ifftFlagR</code> Selects forward (=0) or inverse (=1) transform. + <code>bitReverseFlagR</code> Selects bit reversed output (=0) or normal order + output (=1). + <code>twidCoefRModifier</code> stride modifier for the twiddle factor table. + The value is based on the FFT length; + <code>pTwiddleAReal</code>points to the A array of twiddle coefficients; + <code>pTwiddleBReal</code>points to the B array of twiddle coefficients; + <code>pCfft</code> points to the CFFT Instance structure. The CFFT structure + must also be initialized. +@par + Note that with MVE versions you can't initialize instance structures directly and **must + use the initialization function**. + + @par Neon version + The neon version has a different API. + The input and output buffers must be + different. + There is a temporary buffer that is not optional. + + The bit reverse flag is not more + available in Neon version. + + + @code + void arm_rfft_fast_f32( + const arm_rfft_fast_instance_f32 * S, + float32_t * p, + float32_t * pOut, + float32_t *tmpbuf, + uint8_t ifftFlag); + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + */ + +/** + @defgroup DeprecatedRealFFT Deprecated Real FFT Functions +*/ + +/** + @defgroup RealFFTF32 Real FFT F32 Functions +*/ +/** + @addtogroup RealFFTF32 + @{ +*/ + +/** + @brief Processing function for the floating-point real FFT. + @param[in] S points to an arm_rfft_fast_instance_f32 structure + @param[in] p points to input buffer (Source buffer is modified by this function.) + @param[in] pOut points to output buffer + @param[in] ifftFlag + - value = 0: RFFT + - value = 1: RIFFT + + @par Neon version + The neon version has a different API. + The input and output buffers must be + different. + There is a temporary buffer. + @par + The bit reverse flag is not more + available in Neon version. + + @par + @code + void arm_rfft_fast_f32( + const arm_rfft_fast_instance_f32 * S, + const float32_t * p, + float32_t * pOut, + float32_t *tmpbuf, + uint8_t ifftFlag); + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". +*/ + +#if defined(ARM_MATH_NEON) + +#include "CMSIS_NE10_types.h" +#include "CMSIS_NE10_fft.h" + +/* + +p size : nfft reals +pOut size : nfft reals (nfft/2 complex) +tmpBuf size : 2*nfft reals (nfft complex) + +*/ +ARM_DSP_ATTRIBUTE void arm_rfft_fast_f32( + const arm_rfft_fast_instance_f32 * S, + const float32_t * p, + float32_t * pOut, + float32_t *tmpbuf, + uint8_t ifftFlag) +{ +/* Calculation of Real FFT */ + if (!ifftFlag) + { + arm_ne10_fft_r2c_1d_float32_neon (S,p,pOut,tmpbuf); + } + else + { + arm_ne10_fft_c2r_1d_float32_neon (S,p,pOut,tmpbuf); + } +} +#else +ARM_DSP_ATTRIBUTE void arm_rfft_fast_f32( + const arm_rfft_fast_instance_f32 * S, + float32_t * p, + float32_t * pOut, + uint8_t ifftFlag) +{ + const arm_cfft_instance_f32 * Sint = &(S->Sint); + + /* Calculation of Real FFT */ + if (ifftFlag) + { + /* Real FFT compression */ + merge_rfft_f32(S, p, pOut); + /* Complex radix-4 IFFT process */ + arm_cfft_f32( Sint, pOut, ifftFlag, 1); + } + else + { + /* Calculation of RFFT of input */ + arm_cfft_f32( Sint, p, ifftFlag, 1); + + /* Real FFT extraction */ + stage_rfft_f32(S, p, pOut); + } +} +#endif +/** +* @} end of RealFFTF32 group +*/ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f64.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f64.c new file mode 100755 index 0000000..80fede3 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_f64.c @@ -0,0 +1,236 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_fast_f64.c + * Description: RFFT & RIFFT Double precision Floating point process function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +static void stage_rfft_f64( + const arm_rfft_fast_instance_f64 * S, + const float64_t * p, + float64_t * pOut) +{ + uint32_t k; /* Loop Counter */ + float64_t twR, twI; /* RFFT Twiddle coefficients */ + const float64_t * pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float64_t *pA = p; /* increasing pointer */ + const float64_t *pB = p; /* decreasing pointer */ + float64_t xAR, xAI, xBR, xBI; /* temporary variables */ + float64_t t1a, t1b; /* temporary variables */ + float64_t p0, p1, p2, p3; /* temporary variables */ + + + k = (S->Sint).fftLen - 1; + + /* Pack first and last sample of the frequency domain together */ + + xBR = pB[0]; + xBI = pB[1]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++ ; + twI = *pCoeff++ ; + + // U1 = XA(1) + XB(1); % It is real + t1a = xBR + xAR ; + + // U2 = XB(1) - XA(1); % It is imaginary + t1b = xBI + xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + *pOut++ = 0.5 * ( t1a + t1b ); + *pOut++ = 0.5 * ( t1a - t1b ); + + // XA(1) = 1/2*( U1 - imag(U2) + i*( U1 +imag(U2) )); + pB = p + 2*k; + pA += 2; + + do + { + /* + function X = my_split_rfft(X, ifftFlag) + % X is a series of real numbers + L = length(X); + XC = X(1:2:end) +i*X(2:2:end); + XA = fft(XC); + XB = conj(XA([1 end:-1:2])); + TW = i*exp(-2*pi*i*[0:L/2-1]/L).'; + for l = 2:L/2 + XA(l) = 1/2 * (XA(l) + XB(l) + TW(l) * (XB(l) - XA(l))); + end + XA(1) = 1/2* (XA(1) + XB(1) + TW(1) * (XB(1) - XA(1))) + i*( 1/2*( XA(1) + XB(1) + i*( XA(1) - XB(1)))); + X = XA; + */ + + xBI = pB[1]; + xBR = pB[0]; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = xBR - xAR ; + t1b = xBI + xAI ; + + // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI); + // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI); + p0 = twR * t1a; + p1 = twI * t1a; + p2 = twR * t1b; + p3 = twI * t1b; + + *pOut++ = 0.5 * (xAR + xBR + p0 + p3 ); //xAR + *pOut++ = 0.5 * (xAI - xBI + p1 - p2 ); //xAI + + pA += 2; + pB -= 2; + k--; + } while (k > 0U); +} + +/* Prepares data for inverse cfft */ +static void merge_rfft_f64( + const arm_rfft_fast_instance_f64 * S, + const float64_t * p, + float64_t * pOut) +{ + uint32_t k; /* Loop Counter */ + float64_t twR, twI; /* RFFT Twiddle coefficients */ + const float64_t *pCoeff = S->pTwiddleRFFT; /* Points to RFFT Twiddle factors */ + const float64_t *pA = p; /* increasing pointer */ + const float64_t *pB = p; /* decreasing pointer */ + float64_t xAR, xAI, xBR, xBI; /* temporary variables */ + float64_t t1a, t1b, r, s, t, u; /* temporary variables */ + + k = (S->Sint).fftLen - 1; + + xAR = pA[0]; + xAI = pA[1]; + + pCoeff += 2 ; + + *pOut++ = 0.5 * ( xAR + xAI ); + *pOut++ = 0.5 * ( xAR - xAI ); + + pB = p + 2*k ; + pA += 2 ; + + while (k > 0U) + { + /* G is half of the frequency complex spectrum */ + //for k = 2:N + // Xk(k) = 1/2 * (G(k) + conj(G(N-k+2)) + Tw(k)*( G(k) - conj(G(N-k+2)))); + xBI = pB[1] ; + xBR = pB[0] ; + xAR = pA[0]; + xAI = pA[1]; + + twR = *pCoeff++; + twI = *pCoeff++; + + t1a = xAR - xBR ; + t1b = xAI + xBI ; + + r = twR * t1a; + s = twI * t1b; + t = twI * t1a; + u = twR * t1b; + + // real(tw * (xA - xB)) = twR * (xAR - xBR) - twI * (xAI - xBI); + // imag(tw * (xA - xB)) = twI * (xAR - xBR) + twR * (xAI - xBI); + *pOut++ = 0.5 * (xAR + xBR - r - s ); //xAR + *pOut++ = 0.5 * (xAI - xBI + t - u ); //xAI + + pA += 2; + pB -= 2; + k--; + } + +} + +/** + @ingroup RealFFT +*/ + +/** + @defgroup RealFFTF64 Real FFT F64 Functions +*/ + +/** + @addtogroup RealFFTF64 + @{ +*/ + +/** + @brief Processing function for the Double Precision floating-point real FFT. + @param[in] S points to an arm_rfft_fast_instance_f64 structure + @param[in] p points to input buffer (Source buffer is modified by this function.) + @param[in] pOut points to output buffer + @param[in] ifftFlag + - value = 0: RFFT + - value = 1: RIFFT + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". +*/ + +ARM_DSP_ATTRIBUTE void arm_rfft_fast_f64( + arm_rfft_fast_instance_f64 * S, + float64_t * p, + float64_t * pOut, + uint8_t ifftFlag) +{ + arm_cfft_instance_f64 * Sint = &(S->Sint); + Sint->fftLen = S->fftLenRFFT / 2; + + /* Calculation of Real FFT */ + if (ifftFlag) + { + /* Real FFT compression */ + merge_rfft_f64(S, p, pOut); + + /* Complex radix-4 IFFT process */ + arm_cfft_f64( Sint, pOut, ifftFlag, 1); + } + else + { + /* Calculation of RFFT of input */ + arm_cfft_f64( Sint, p, ifftFlag, 1); + + /* Real FFT extraction */ + stage_rfft_f64(S, p, pOut); + } +} + +/** +* @} end of RealFFTF64 group +*/ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f16.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f16.c new file mode 100755 index 0000000..14b855d --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f16.c @@ -0,0 +1,407 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_fast_init_f16.c + * Description: Split Radix Decimation in Frequency CFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions_f16.h" +#include "arm_common_tables_f16.h" +#include "arm_const_structs_f16.h" + +#if defined(ARM_FLOAT16_SUPPORTED) + +/** + @ingroup RealFFT + */ + +/** + @addtogroup RealFFTF16 + @{ + */ + + +/** + @brief Initialization function for the 32pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON_FLOAT16) +#include "arm_neon_tables_f16.h" +#define RFFT_INIT(LEN) \ + S->nfft = LEN; \ + S->r_twiddles = arm_neon_rfft_twiddles_##LEN##_f16; \ + S->r_factors = arm_neon_rfft_factors_##LEN##_f16; \ + \ + S->r_twiddles_neon = arm_neon_rfft_twiddles_neon_##LEN##_f16; \ + S->r_factors_neon = arm_neon_rfft_factors_neon_##LEN##_f16; \ + \ + S->r_twiddles_backward = S->r_twiddles + 2*ARM_NE10_OFFSET_BACKWARD_TWID_RFFT_##LEN##_F16; \ + S->r_twiddles_neon_backward = S->r_twiddles_neon + 2*ARM_NE10_OFFSET_BACKWARD_TWID_NEON_##LEN##_F16;\ + \ + S->r_super_twiddles_neon = arm_neon_rfft_super_twiddles_neon_##LEN##_f16; + +#define FAST_INIT_FUNC(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_##LEN##_f16( arm_rfft_fast_instance_f16 * S )\ +{ \ + \ + if( !S ) return ARM_MATH_ARGUMENT_ERROR; \ + \ + RFFT_INIT(LEN); \ + \ + return ARM_MATH_SUCCESS; \ +} + +#endif + +#if defined(ARM_MATH_NEON_FLOAT16) + +FAST_INIT_FUNC(32) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_32_f16( arm_rfft_fast_instance_f16 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_16_f16(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + + S->fftLenRFFT = 32U; + S->pTwiddleRFFT = (float16_t *) twiddleCoefF16_rfft_32; + + return ARM_MATH_SUCCESS; +} +#endif + +/** + @brief Initialization function for the 64pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON_FLOAT16) + +FAST_INIT_FUNC(64) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_64_f16( arm_rfft_fast_instance_f16 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_32_f16(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 64U; + + S->pTwiddleRFFT = (float16_t *) twiddleCoefF16_rfft_64; + + return ARM_MATH_SUCCESS; +} +#endif + +/** + @brief Initialization function for the 128pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON_FLOAT16) + +FAST_INIT_FUNC(128) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_128_f16( arm_rfft_fast_instance_f16 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_64_f16(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 128; + + S->pTwiddleRFFT = (float16_t *) twiddleCoefF16_rfft_128; + + return ARM_MATH_SUCCESS; +} +#endif + +/** + @brief Initialization function for the 256pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected +*/ +#if defined(ARM_MATH_NEON_FLOAT16) + +FAST_INIT_FUNC(256) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_256_f16( arm_rfft_fast_instance_f16 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_128_f16(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 256U; + + S->pTwiddleRFFT = (float16_t *) twiddleCoefF16_rfft_256; + + return ARM_MATH_SUCCESS; +} +#endif +/** + @brief Initialization function for the 512pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON_FLOAT16) + +FAST_INIT_FUNC(512) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_512_f16( arm_rfft_fast_instance_f16 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_256_f16(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 512U; + + S->pTwiddleRFFT = (float16_t *) twiddleCoefF16_rfft_512; + + return ARM_MATH_SUCCESS; +} +#endif + +/** + @brief Initialization function for the 1024pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON_FLOAT16) + +FAST_INIT_FUNC(1024) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_1024_f16( arm_rfft_fast_instance_f16 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_512_f16(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 1024U; + + S->pTwiddleRFFT = (float16_t *) twiddleCoefF16_rfft_1024; + + return ARM_MATH_SUCCESS; +} +#endif +/** + @brief Initialization function for the 2048pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ +#if defined(ARM_MATH_NEON_FLOAT16) + +FAST_INIT_FUNC(2048) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_2048_f16( arm_rfft_fast_instance_f16 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_1024_f16(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 2048U; + + S->pTwiddleRFFT = (float16_t *) twiddleCoefF16_rfft_2048; + + return ARM_MATH_SUCCESS; +} +#endif +/** +* @brief Initialization function for the 4096pt floating-point real FFT. +* @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ +#if defined(ARM_MATH_NEON_FLOAT16) + +FAST_INIT_FUNC(4096) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_4096_f16( arm_rfft_fast_instance_f16 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_2048_f16(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 4096U; + + S->pTwiddleRFFT = (float16_t *) twiddleCoefF16_rfft_4096; + + return ARM_MATH_SUCCESS; +} +#endif + +/** + @brief Generic initialization function for the floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f16 structure + @param[in] fftLen length of the Real Sequence + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Description + The parameter <code>fftLen</code> specifies the length of RFFT/CIFFT process. + Supported FFT Lengths are 32, 64, 128, 256, 512, 1024, 2048, 4096. + + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_f16( + arm_rfft_fast_instance_f16 * S, + uint16_t fftLen) +{ + arm_status status; + + + switch (fftLen) + { + case 4096U: + status = arm_rfft_fast_init_4096_f16(S); + break; + case 2048U: + status = arm_rfft_fast_init_2048_f16(S); + break; + case 1024U: + status = arm_rfft_fast_init_1024_f16(S); + break; + case 512U: + status = arm_rfft_fast_init_512_f16(S); + break; + case 256U: + status = arm_rfft_fast_init_256_f16(S); + break; + case 128U: + status = arm_rfft_fast_init_128_f16(S); + break; + case 64U: + status = arm_rfft_fast_init_64_f16(S); + break; + case 32U: + status = arm_rfft_fast_init_32_f16(S); + break; + default: + return(ARM_MATH_ARGUMENT_ERROR); + break; + } + + return(status); + +} + +/** + @} end of RealFFTF16 group + */ + + #if defined(RFFT_INIT) + #undef RFFT_INIT + #endif + + #if defined(FAST_INIT_FUNC) + #undef FAST_INIT_FUNC + #endif +#endif /* #if defined(ARM_FLOAT16_SUPPORTED) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f32.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f32.c new file mode 100755 index 0000000..04052c5 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f32.c @@ -0,0 +1,386 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_fast_init_f32.c + * Description: Split Radix Decimation in Frequency CFFT Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + +/** + @ingroup RealFFT + */ + +/** + @addtogroup RealFFTF32 + @{ + */ + + +/** + @brief Initialization function for the 32pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON) +#include "arm_neon_tables.h" +#define RFFT_INIT(LEN) \ + S->nfft = LEN; \ + S->r_twiddles = arm_neon_rfft_twiddles_##LEN##_f32; \ + S->r_factors = arm_neon_rfft_factors_##LEN##_f32; \ + \ + S->r_twiddles_neon = arm_neon_rfft_twiddles_neon_##LEN##_f32; \ + S->r_factors_neon = arm_neon_rfft_factors_neon_##LEN##_f32; \ + \ + S->r_twiddles_backward = S->r_twiddles + 2*ARM_NE10_OFFSET_BACKWARD_TWID_RFFT_##LEN##_F32; \ + S->r_twiddles_neon_backward = S->r_twiddles_neon + 2*ARM_NE10_OFFSET_BACKWARD_TWID_NEON_##LEN##_F32;\ + \ + S->r_super_twiddles_neon = arm_neon_rfft_super_twiddles_neon_##LEN##_f32; + +#define FAST_INIT_FUNC(LEN) \ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_##LEN##_f32( arm_rfft_fast_instance_f32 * S )\ +{ \ + \ + if( !S ) return ARM_MATH_ARGUMENT_ERROR; \ + \ + RFFT_INIT(LEN); \ + \ + return ARM_MATH_SUCCESS; \ +} + +#endif + +#if defined(ARM_MATH_NEON) + +FAST_INIT_FUNC(32) + +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_32_f32( arm_rfft_fast_instance_f32 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_16_f32(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + + S->fftLenRFFT = 32U; + S->pTwiddleRFFT = (float32_t *) twiddleCoef_rfft_32; + + return ARM_MATH_SUCCESS; +} +#endif +/** + @brief Initialization function for the 64pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ +#if defined(ARM_MATH_NEON) +FAST_INIT_FUNC(64) +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_64_f32( arm_rfft_fast_instance_f32 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_32_f32(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 64U; + + S->pTwiddleRFFT = (float32_t *) twiddleCoef_rfft_64; + + return ARM_MATH_SUCCESS; +} +#endif + +/** + @brief Initialization function for the 128pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON) +FAST_INIT_FUNC(128) +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_128_f32( arm_rfft_fast_instance_f32 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_64_f32(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 128; + + S->pTwiddleRFFT = (float32_t *) twiddleCoef_rfft_128; + + return ARM_MATH_SUCCESS; +} +#endif +/** + @brief Initialization function for the 256pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected +*/ + +#if defined(ARM_MATH_NEON) +FAST_INIT_FUNC(256) +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_256_f32( arm_rfft_fast_instance_f32 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_128_f32(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 256U; + + S->pTwiddleRFFT = (float32_t *) twiddleCoef_rfft_256; + + return ARM_MATH_SUCCESS; +} +#endif +/** + @brief Initialization function for the 512pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON) +FAST_INIT_FUNC(512) +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_512_f32( arm_rfft_fast_instance_f32 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_256_f32(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 512U; + + S->pTwiddleRFFT = (float32_t *) twiddleCoef_rfft_512; + + return ARM_MATH_SUCCESS; +} +#endif +/** + @brief Initialization function for the 1024pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON) +FAST_INIT_FUNC(1024) +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_1024_f32( arm_rfft_fast_instance_f32 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_512_f32(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 1024U; + + S->pTwiddleRFFT = (float32_t *) twiddleCoef_rfft_1024; + + return ARM_MATH_SUCCESS; +} +#endif +/** + @brief Initialization function for the 2048pt floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ +#if defined(ARM_MATH_NEON) +FAST_INIT_FUNC(2048) +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_2048_f32( arm_rfft_fast_instance_f32 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_1024_f32(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 2048U; + + S->pTwiddleRFFT = (float32_t *) twiddleCoef_rfft_2048; + + return ARM_MATH_SUCCESS; +} +#endif +/** +* @brief Initialization function for the 4096pt floating-point real FFT. +* @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +#if defined(ARM_MATH_NEON) +FAST_INIT_FUNC(4096) +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_4096_f32( arm_rfft_fast_instance_f32 * S ) { + + arm_status status; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + status=arm_cfft_init_2048_f32(&(S->Sint)); + if (status != ARM_MATH_SUCCESS) + { + return(status); + } + S->fftLenRFFT = 4096U; + + S->pTwiddleRFFT = (float32_t *) twiddleCoef_rfft_4096; + + return ARM_MATH_SUCCESS; +} +#endif +/** + @brief Generic initialization function for the floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f32 structure + @param[in] fftLen length of the Real Sequence + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Description + The parameter <code>fftLen</code> specifies the length of RFFT/CIFFT process. + Supported FFT Lengths are 32, 64, 128, 256, 512, 1024, 2048, 4096. + + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_f32( + arm_rfft_fast_instance_f32 * S, + uint16_t fftLen) +{ + arm_status status; + + + switch (fftLen) + { + case 4096U: + status = arm_rfft_fast_init_4096_f32(S); + break; + case 2048U: + status = arm_rfft_fast_init_2048_f32(S); + break; + case 1024U: + status = arm_rfft_fast_init_1024_f32(S); + break; + case 512U: + status = arm_rfft_fast_init_512_f32(S); + break; + case 256U: + status = arm_rfft_fast_init_256_f32(S); + break; + case 128U: + status = arm_rfft_fast_init_128_f32(S); + break; + case 64U: + status = arm_rfft_fast_init_64_f32(S); + break; + case 32U: + status = arm_rfft_fast_init_32_f32(S); + break; + default: + return(ARM_MATH_ARGUMENT_ERROR); + break; + } + + return(status); + +} + +#if defined(RFFT_INIT) + #undef RFFT_INIT + #endif + + #if defined(FAST_INIT_FUNC) + #undef FAST_INIT_FUNC + #endif + +/** + @} end of RealFFTF32 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f64.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f64.c new file mode 100755 index 0000000..8f7c600 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_fast_init_f64.c @@ -0,0 +1,328 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_fast_init_f64.c + * Description: Split Radix Decimation in Frequency CFFT Double Precision Floating point processing function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" + +/** + @ingroup RealFFT + */ + +/** + @addtogroup RealFFTF64 + @{ + */ + + +/** + @brief Initialization function for the 32pt double precision floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_32_f64( arm_rfft_fast_instance_f64 * S ) { + + arm_cfft_instance_f64 * Sint; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + Sint = &(S->Sint); + Sint->fftLen = 16U; + S->fftLenRFFT = 32U; + + Sint->bitRevLength = ARMBITREVINDEXTABLEF64_16_TABLE_LENGTH; + Sint->pBitRevTable = (uint16_t *)armBitRevIndexTableF64_16; + Sint->pTwiddle = (float64_t *) twiddleCoefF64_16; + S->pTwiddleRFFT = (float64_t *) twiddleCoefF64_rfft_32; + + return ARM_MATH_SUCCESS; +} + + +/** + @brief Initialization function for the 64pt Double Precision floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_64_f64( arm_rfft_fast_instance_f64 * S ) { + + arm_cfft_instance_f64 * Sint; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + Sint = &(S->Sint); + Sint->fftLen = 32U; + S->fftLenRFFT = 64U; + + Sint->bitRevLength = ARMBITREVINDEXTABLEF64_32_TABLE_LENGTH; + Sint->pBitRevTable = (uint16_t *)armBitRevIndexTableF64_32; + Sint->pTwiddle = (float64_t *) twiddleCoefF64_32; + S->pTwiddleRFFT = (float64_t *) twiddleCoefF64_rfft_64; + + return ARM_MATH_SUCCESS; +} + + +/** + @brief Initialization function for the 128pt Double Precision floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_128_f64( arm_rfft_fast_instance_f64 * S ) { + + arm_cfft_instance_f64 * Sint; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + Sint = &(S->Sint); + Sint->fftLen = 64U; + S->fftLenRFFT = 128U; + + Sint->bitRevLength = ARMBITREVINDEXTABLEF64_64_TABLE_LENGTH; + Sint->pBitRevTable = (uint16_t *)armBitRevIndexTableF64_64; + Sint->pTwiddle = (float64_t *) twiddleCoefF64_64; + S->pTwiddleRFFT = (float64_t *) twiddleCoefF64_rfft_128; + + return ARM_MATH_SUCCESS; +} + + +/** + @brief Initialization function for the 256pt Double Precision floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected +*/ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_256_f64( arm_rfft_fast_instance_f64 * S ) { + + arm_cfft_instance_f64 * Sint; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + Sint = &(S->Sint); + Sint->fftLen = 128U; + S->fftLenRFFT = 256U; + + Sint->bitRevLength = ARMBITREVINDEXTABLEF64_128_TABLE_LENGTH; + Sint->pBitRevTable = (uint16_t *)armBitRevIndexTableF64_128; + Sint->pTwiddle = (float64_t *) twiddleCoefF64_128; + S->pTwiddleRFFT = (float64_t *) twiddleCoefF64_rfft_256; + + return ARM_MATH_SUCCESS; +} + + +/** + @brief Initialization function for the 512pt Double Precision floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_512_f64( arm_rfft_fast_instance_f64 * S ) { + + arm_cfft_instance_f64 * Sint; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + Sint = &(S->Sint); + Sint->fftLen = 256U; + S->fftLenRFFT = 512U; + + Sint->bitRevLength = ARMBITREVINDEXTABLEF64_256_TABLE_LENGTH; + Sint->pBitRevTable = (uint16_t *)armBitRevIndexTableF64_256; + Sint->pTwiddle = (float64_t *) twiddleCoefF64_256; + S->pTwiddleRFFT = (float64_t *) twiddleCoefF64_rfft_512; + + return ARM_MATH_SUCCESS; +} + +/** + @brief Initialization function for the 1024pt Double Precision floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_1024_f64( arm_rfft_fast_instance_f64 * S ) { + + arm_cfft_instance_f64 * Sint; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + Sint = &(S->Sint); + Sint->fftLen = 512U; + S->fftLenRFFT = 1024U; + + Sint->bitRevLength = ARMBITREVINDEXTABLEF64_512_TABLE_LENGTH; + Sint->pBitRevTable = (uint16_t *)armBitRevIndexTableF64_512; + Sint->pTwiddle = (float64_t *) twiddleCoefF64_512; + S->pTwiddleRFFT = (float64_t *) twiddleCoefF64_rfft_1024; + + return ARM_MATH_SUCCESS; +} + +/** + @brief Initialization function for the 2048pt Double Precision floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_2048_f64( arm_rfft_fast_instance_f64 * S ) { + + arm_cfft_instance_f64 * Sint; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + Sint = &(S->Sint); + Sint->fftLen = 1024U; + S->fftLenRFFT = 2048U; + + Sint->bitRevLength = ARMBITREVINDEXTABLEF64_1024_TABLE_LENGTH; + Sint->pBitRevTable = (uint16_t *)armBitRevIndexTableF64_1024; + Sint->pTwiddle = (float64_t *) twiddleCoefF64_1024; + S->pTwiddleRFFT = (float64_t *) twiddleCoefF64_rfft_2048; + + return ARM_MATH_SUCCESS; +} + +/** +* @brief Initialization function for the 4096pt Double Precision floating-point real FFT. +* @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : an error is detected + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_4096_f64( arm_rfft_fast_instance_f64 * S ) { + + arm_cfft_instance_f64 * Sint; + + if( !S ) return ARM_MATH_ARGUMENT_ERROR; + + Sint = &(S->Sint); + Sint->fftLen = 2048U; + S->fftLenRFFT = 4096U; + + Sint->bitRevLength = ARMBITREVINDEXTABLEF64_2048_TABLE_LENGTH; + Sint->pBitRevTable = (uint16_t *)armBitRevIndexTableF64_2048; + Sint->pTwiddle = (float64_t *) twiddleCoefF64_2048; + S->pTwiddleRFFT = (float64_t *) twiddleCoefF64_rfft_4096; + + return ARM_MATH_SUCCESS; +} + +/** + @brief Generic initialization function for the Double Precision floating-point real FFT. + @param[in,out] S points to an arm_rfft_fast_instance_f64 structure + @param[in] fftLen length of the Real Sequence + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLen</code> is not a supported length + + @par Description + The parameter <code>fftLen</code> specifies the length of RFFT/CIFFT process. + Supported FFT Lengths are 32, 64, 128, 256, 512, 1024, 2048, 4096. + + @par + This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. + + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + + @par + If you use CMSIS-DSP as a library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + + */ + +ARM_DSP_ATTRIBUTE arm_status arm_rfft_fast_init_f64( + arm_rfft_fast_instance_f64 * S, + uint16_t fftLen) +{ + arm_status status; + + + switch (fftLen) + { + case 4096U: + status = arm_rfft_fast_init_4096_f64(S); + break; + case 2048U: + status = arm_rfft_fast_init_2048_f64(S); + break; + case 1024U: + status = arm_rfft_fast_init_1024_f64(S); + break; + case 512U: + status = arm_rfft_fast_init_512_f64(S); + break; + case 256U: + status = arm_rfft_fast_init_256_f64(S); + break; + case 128U: + status = arm_rfft_fast_init_128_f64(S); + break; + case 64U: + status = arm_rfft_fast_init_64_f64(S); + break; + case 32U: + status = arm_rfft_fast_init_32_f64(S); + break; + default: + return(ARM_MATH_ARGUMENT_ERROR); + break; + } + + return(status); + +} + +/** + @} end of RealFFTF64 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_init_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_init_q15.c new file mode 100755 index 0000000..4b0b783 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_init_q15.c @@ -0,0 +1,487 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_init_q15.c + * Description: RFFT & RIFFT Q15 initialisation function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" +#include "arm_const_structs.h" + +/** + @ingroup RealFFT +*/ + +/** + @defgroup RealFFTQ15 Real FFT Q15 Functions +*/ + +/** + @addtogroup RealFFTQ15 + @{ + */ + + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) +#define RFFTINIT_Q15(LEN,CFFTLEN,TWIDMOD) \ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_##LEN##_q15( arm_rfft_instance_q15 * S, \ + uint32_t ifftFlagR, \ + uint32_t bitReverseFlag ) \ +{ \ + \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + \ + /* Initialize the Real FFT length */ \ + S->fftLenReal = (uint16_t) LEN; \ + \ + /* Initialize the Twiddle coefficientA pointer */ \ + S->pTwiddleAReal = (q15_t *) realCoefAQ15; \ + \ + /* Initialize the Twiddle coefficientB pointer */ \ + S->pTwiddleBReal = (q15_t *) realCoefBQ15; \ + \ + /* Initialize the Flag for selection of RFFT or RIFFT */ \ + S->ifftFlagR = (uint8_t) ifftFlagR; \ + \ + /* Initialize the Flag for calculation Bit reversal or not */\ + S->bitReverseFlagR = (uint8_t) bitReverseFlag; \ + \ + S->twidCoefRModifier = TWIDMOD; \ + \ + status=arm_cfft_init_##CFFTLEN##_q15(&(S->cfftInst)); \ + \ + /* return the status of RFFT Init function */ \ + return (status); \ +} +#elif defined(ARM_MATH_NEON) +#define RFFTINIT_Q15(LEN,CFFTLEN,TWIDMOD) \ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_##LEN##_q15( arm_rfft_instance_q15 * S )\ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + S->nfft = LEN; \ + S->ncfft = LEN >> 1; \ + \ + S->twiddles = arm_neon_rfft_twiddles_##LEN##_q15; \ + S->factors = arm_neon_rfft_factors_##LEN##_q15; \ + \ + S->super_twiddles = arm_neon_rfft_super_twiddles_neon_##LEN##_q15; \ + \ + /* return the status of RFFT Init function */ \ + return (status); \ +} +#include "arm_neon_tables.h" + + +#else +#define RFFTINIT_Q15(LEN,CFFTLEN,TWIDMOD) \ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_##LEN##_q15( arm_rfft_instance_q15 * S, \ + uint32_t ifftFlagR, \ + uint32_t bitReverseFlag ) \ +{ \ + /* Initialize the Real FFT length */ \ + S->fftLenReal = (uint16_t) LEN; \ + \ + /* Initialize the Twiddle coefficientA pointer */ \ + S->pTwiddleAReal = (q15_t *) realCoefAQ15; \ + \ + /* Initialize the Twiddle coefficientB pointer */ \ + S->pTwiddleBReal = (q15_t *) realCoefBQ15; \ + \ + /* Initialize the Flag for selection of RFFT or RIFFT */ \ + S->ifftFlagR = (uint8_t) ifftFlagR; \ + \ + /* Initialize the Flag for calculation Bit reversal or not */\ + S->bitReverseFlagR = (uint8_t) bitReverseFlag; \ + \ + S->twidCoefRModifier = TWIDMOD; \ + \ + S->pCfft = &arm_cfft_sR_q15_len##CFFTLEN; \ + \ + /* return the status of RFFT Init function */ \ + return (ARM_MATH_SUCCESS); \ +} +#endif + + +/** + @brief Initialization function for the 8192 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + + */ + +RFFTINIT_Q15(8192,4096,1) + +/** + @brief Initialization function for the 4096 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q15(4096,2048,2) + +/** + @brief Initialization function for the 2048 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q15(2048,1024,4) + +/** + @brief Initialization function for the 1024 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q15(1024,512,8) + +/** + @brief Initialization function for the 512 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q15(512,256,16) + +/** + @brief Initialization function for the 256 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q15(256,128,32) + +/** + @brief Initialization function for the 128 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q15(128,64,64) + +/** + @brief Initialization function for the 64 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q15(64,32,128) + +/** + @brief Initialization function for the 32 pt Q15 real FFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q15(32,16,256) + +/** + @brief Generic initialization function for the Q15 RFFT/RIFFT. + @param[in,out] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] fftLenReal length of the FFT + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par Details + The parameter <code>fftLenReal</code> specifies length of RFFT/RIFFT Process. + Supported FFT Lengths are 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192. + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + @par + If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + + */ +#if defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialization of coef modifier depending on the FFT length */ + switch (fftLenReal) + { + case 8192U: + status = arm_rfft_init_8192_q15( S ); + break; + case 4096U: + status = arm_rfft_init_4096_q15( S ); + break; + case 2048U: + status = arm_rfft_init_2048_q15( S ); + break; + case 1024U: + status = arm_rfft_init_1024_q15( S ); + break; + case 512U: + status = arm_rfft_init_512_q15( S ); + break; + case 256U: + status = arm_rfft_init_256_q15( S ); + break; + case 128U: + status = arm_rfft_init_128_q15( S ); + break; + case 64U: + status = arm_rfft_init_64_q15( S ); + break; + case 32U: + status = arm_rfft_init_32_q15( S ); + break; + default: + /* Reporting argument error if rfftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + /* return the status of RFFT Init function */ + return (status); +} +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + + /* Initialization of coef modifier depending on the FFT length */ + switch (fftLenReal) + { + case 8192U: + status = arm_rfft_init_8192_q15( S,ifftFlagR,bitReverseFlag ); + break; + case 4096U: + status = arm_rfft_init_4096_q15( S,ifftFlagR,bitReverseFlag ); + break; + case 2048U: + status = arm_rfft_init_2048_q15( S,ifftFlagR,bitReverseFlag ); + break; + case 1024U: + status = arm_rfft_init_1024_q15( S,ifftFlagR,bitReverseFlag ); + break; + case 512U: + status = arm_rfft_init_512_q15( S,ifftFlagR,bitReverseFlag ); + break; + case 256U: + status = arm_rfft_init_256_q15( S,ifftFlagR,bitReverseFlag ); + break; + case 128U: + status = arm_rfft_init_128_q15( S,ifftFlagR,bitReverseFlag ); + break; + case 64U: + status = arm_rfft_init_64_q15( S,ifftFlagR,bitReverseFlag ); + break; + case 32U: + status = arm_rfft_init_32_q15( S,ifftFlagR,bitReverseFlag ); + break; + default: + /* Reporting argument error if rfftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + /* return the status of RFFT Init function */ + return (status); +} +#endif + +/** + @} end of RealFFTQ15 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_init_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_init_q31.c new file mode 100755 index 0000000..76fbcd1 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_init_q31.c @@ -0,0 +1,482 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_init_q31.c + * Description: RFFT & RIFFT Q31 initialisation function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" +#include "arm_common_tables.h" +#include "arm_const_structs.h" + +/** + @ingroup RealFFT +*/ + +/** + @defgroup RealFFTQ31 Real FFT Q31 Functions +*/ + +/** + @addtogroup RealFFTQ31 + @{ + */ + + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) +#define RFFTINIT_Q31(LEN,CFFTLEN,TWIDMOD) \ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_##LEN##_q31( arm_rfft_instance_q31 * S, \ + uint32_t ifftFlagR, \ + uint32_t bitReverseFlag ) \ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_ARGUMENT_ERROR; \ + \ + /* Initialize the Real FFT length */ \ + S->fftLenReal = (uint16_t) LEN; \ + \ + /* Initialize the Twiddle coefficientA pointer */ \ + S->pTwiddleAReal = (q31_t *) realCoefAQ31; \ + \ + /* Initialize the Twiddle coefficientB pointer */ \ + S->pTwiddleBReal = (q31_t *) realCoefBQ31; \ + \ + /* Initialize the Flag for selection of RFFT or RIFFT */ \ + S->ifftFlagR = (uint8_t) ifftFlagR; \ + \ + /* Initialize the Flag for calculation Bit reversal or not */\ + S->bitReverseFlagR = (uint8_t) bitReverseFlag; \ + \ + S->twidCoefRModifier = TWIDMOD; \ + \ + status=arm_cfft_init_##CFFTLEN##_q31(&(S->cfftInst)); \ + \ + /* return the status of RFFT Init function */ \ + return (status); \ +} +#elif defined(ARM_MATH_NEON) +#define RFFTINIT_Q31(LEN,CFFTLEN,TWIDMOD) \ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_##LEN##_q31( arm_rfft_instance_q31 * S )\ +{ \ + /* Initialise the default arm status */ \ + arm_status status = ARM_MATH_SUCCESS; \ + S->nfft = LEN; \ + S->ncfft = LEN >> 1; \ + \ + S->twiddles = arm_neon_rfft_twiddles_##LEN##_q31; \ + S->factors = arm_neon_rfft_factors_##LEN##_q31; \ + \ + S->super_twiddles = arm_neon_rfft_super_twiddles_neon_##LEN##_q31; \ + \ + /* return the status of RFFT Init function */ \ + return (status); \ +} +#include "arm_neon_tables.h" + + +#else +#define RFFTINIT_Q31(LEN,CFFTLEN,TWIDMOD) \ +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_##LEN##_q31( arm_rfft_instance_q31 * S, \ + uint32_t ifftFlagR, \ + uint32_t bitReverseFlag ) \ +{ \ + /* Initialize the Real FFT length */ \ + S->fftLenReal = (uint16_t) LEN; \ + \ + /* Initialize the Twiddle coefficientA pointer */ \ + S->pTwiddleAReal = (q31_t *) realCoefAQ31; \ + \ + /* Initialize the Twiddle coefficientB pointer */ \ + S->pTwiddleBReal = (q31_t *) realCoefBQ31; \ + \ + /* Initialize the Flag for selection of RFFT or RIFFT */ \ + S->ifftFlagR = (uint8_t) ifftFlagR; \ + \ + /* Initialize the Flag for calculation Bit reversal or not */\ + S->bitReverseFlagR = (uint8_t) bitReverseFlag; \ + \ + S->twidCoefRModifier = TWIDMOD; \ + \ + S->pCfft = &arm_cfft_sR_q31_len##CFFTLEN; \ + \ + /* return the status of RFFT Init function */ \ + return (ARM_MATH_SUCCESS); \ +} +#endif + + +/** + @brief Initialization function for the 8192 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(8192,4096,1) + +/** + @brief Initialization function for the 4096 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(4096,2048,2) + +/** + @brief Initialization function for the 2048 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(2048,1024,4) + +/** + @brief Initialization function for the 1024 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(1024,512,8) + +/** + @brief Initialization function for the 512 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(512,256,16) + +/** + @brief Initialization function for the 256 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(256,128,32) + +/** + @brief Initialization function for the 128 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(128,64,64) + +/** + @brief Initialization function for the 64 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(64,32,128) + +/** + @brief Initialization function for the 32 pt Q31 real FFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + */ +RFFTINIT_Q31(32,16,256) + + +/** + @brief Generic initialization function for the Q31 RFFT/RIFFT. + @param[in,out] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] fftLenReal length of the FFT + @param[in] ifftFlagR flag that selects transform direction + - value = 0: forward transform + - value = 1: inverse transform + @param[in] bitReverseFlag flag that enables / disables bit reversal of output + - value = 0: disables bit reversal of output + - value = 1: enables bit reversal of output + @return execution status + - \ref ARM_MATH_SUCCESS : Operation successful + - \ref ARM_MATH_ARGUMENT_ERROR : <code>fftLenReal</code> is not a supported length + + @par Details + The parameter <code>fftLenReal</code> specifies length of RFFT/RIFFT Process. + Supported FFT Lengths are 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192. + @par + The parameter <code>ifftFlagR</code> controls whether a forward or inverse transform is computed. + Set(=1) ifftFlagR to calculate RIFFT, otherwise RFFT is calculated. + @par + The parameter <code>bitReverseFlag</code> controls whether output is in normal order or bit reversed order. + Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. + @par + This function also initializes Twiddle factor table. + @par + This function should be used only if you don't know the FFT sizes that + you'll need at build time. The use of this function will prevent the + linker from removing the FFT tables that are not needed and the library + code size will be bigger than needed. + @par + If you use CMSIS-DSP as a static library, and if you know the FFT sizes + that you need at build time, then it is better to use the initialization + functions defined for each FFT size. + +*/ +#if defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + /* Initialization of coef modifier depending on the FFT length */ + switch (fftLenReal) + { + case 8192U: + status = arm_rfft_init_8192_q31( S ); + break; + case 4096U: + status = arm_rfft_init_4096_q31( S ); + break; + case 2048U: + status = arm_rfft_init_2048_q31( S ); + break; + case 1024U: + status = arm_rfft_init_1024_q31( S ); + break; + case 512U: + status = arm_rfft_init_512_q31( S ); + break; + case 256U: + status = arm_rfft_init_256_q31( S ); + break; + case 128U: + status = arm_rfft_init_128_q31( S ); + break; + case 64U: + status = arm_rfft_init_64_q31( S ); + break; + case 32U: + status = arm_rfft_init_32_q31( S ); + break; + default: + /* Reporting argument error if rfftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + /* return the status of RFFT Init function */ + return (status); +} +#else +ARM_DSP_ATTRIBUTE arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag) +{ + /* Initialise the default arm status */ + arm_status status = ARM_MATH_ARGUMENT_ERROR; + /* Initialization of coef modifier depending on the FFT length */ + switch (fftLenReal) + { + case 8192U: + status = arm_rfft_init_8192_q31( S,ifftFlagR,bitReverseFlag ); + break; + case 4096U: + status = arm_rfft_init_4096_q31( S,ifftFlagR,bitReverseFlag ); + break; + case 2048U: + status = arm_rfft_init_2048_q31( S,ifftFlagR,bitReverseFlag ); + break; + case 1024U: + status = arm_rfft_init_1024_q31( S,ifftFlagR,bitReverseFlag ); + break; + case 512U: + status = arm_rfft_init_512_q31( S,ifftFlagR,bitReverseFlag ); + break; + case 256U: + status = arm_rfft_init_256_q31( S,ifftFlagR,bitReverseFlag ); + break; + case 128U: + status = arm_rfft_init_128_q31( S,ifftFlagR,bitReverseFlag ); + break; + case 64U: + status = arm_rfft_init_64_q31( S,ifftFlagR,bitReverseFlag ); + break; + case 32U: + status = arm_rfft_init_32_q31( S,ifftFlagR,bitReverseFlag ); + break; + default: + /* Reporting argument error if rfftSize is not valid value */ + status = ARM_MATH_ARGUMENT_ERROR; + break; + } + + /* return the status of RFFT Init function */ + return (status); +} +#endif /* neon */ +/** + @} end of RealFFTQ31 group + */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_q15.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_q15.c new file mode 100755 index 0000000..cf52c5e --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_q15.c @@ -0,0 +1,585 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_q15.c + * Description: RFFT & RIFFT Q15 process function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +/* ---------------------------------------------------------------------- + * Internal functions prototypes + * -------------------------------------------------------------------- */ + +#if !defined(ARM_MATH_NEON) + +ARM_DSP_ATTRIBUTE void arm_split_rfft_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pATable, + const q15_t * pBTable, + q15_t * pDst, + uint32_t modifier); + +ARM_DSP_ATTRIBUTE void arm_split_rifft_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pATable, + const q15_t * pBTable, + q15_t * pDst, + uint32_t modifier); +#endif + +/** + @addtogroup RealFFTQ15 + @{ + */ + +/** + @brief Processing function for the Q15 RFFT/RIFFT. + @param[in] S points to an instance of the Q15 RFFT/RIFFT structure + @param[in] pSrc points to input buffer (Source buffer is modified by this function.) + @param[out] pDst points to output buffer + + @par Input an output formats + Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process. + Hence the output format is different for different RFFT sizes. + The input and output formats for different RFFT sizes and number of bits to upscale are mentioned in the tables below for RFFT and RIFFT: + @par Input and Output formats for RFFT Q15 + +| RFFT Size | Input Format | Output Format | Number of bits to upscale | +| ---------: | ------------: | -------------: | ------------------------: | +| 32 | 1.15 | 6.10 | 5 | +| 64 | 1.15 | 7.9 | 6 | +| 128 | 1.15 | 8.8 | 7 | +| 256 | 1.15 | 9.7 | 8 | +| 512 | 1.15 | 10.6 | 9 | +| 1024 | 1.15 | 11.5 | 10 | +| 2048 | 1.15 | 12.4 | 11 | +| 4096 | 1.15 | 13.3 | 12 | +| 8192 | 1.15 | 14.2 | 13 | + + @par Input and Output formats for RIFFT Q15 + +| RIFFT Size | Input Format | Output Format | Number of bits to upscale | +| ----------: | ------------: | -------------: | ------------------------: | +| 32 | 1.15 | 6.10 | 0 | +| 64 | 1.15 | 7.9 | 0 | +| 128 | 1.15 | 8.8 | 0 | +| 256 | 1.15 | 9.7 | 0 | +| 512 | 1.15 | 10.6 | 0 | +| 1024 | 1.15 | 11.5 | 0 | +| 2048 | 1.15 | 12.4 | 0 | +| 4096 | 1.15 | 13.3 | 0 | +| 8192 | 1.15 | 14.2 | 0 | + + + + @par Neon implementation + A temporary buffer is required + + @code + void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + q15_t *tmp, + uint8_t ifftFlag + ) + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + + */ + +#if defined(ARM_MATH_NEON) +#include "CMSIS_NE10_types.h" +#include "CMSIS_NE10_fft.h" + + +ARM_DSP_ATTRIBUTE void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + const q15_t * pSrc, + q15_t * pDst, + q15_t *tmp, + uint8_t ifftFlag + ) +{ + if (ifftFlag) + { + arm_ne10_fft_c2r_1d_int16_neon (pDst, + pSrc, + S, + 1, + tmp); + } + else + { + arm_ne10_fft_r2c_1d_int16_neon (pDst, + pSrc, + S, + 1, + tmp); + } +} +#else +ARM_DSP_ATTRIBUTE void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst) +{ +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + const arm_cfft_instance_q15 *S_CFFT = &(S->cfftInst); +#else + const arm_cfft_instance_q15 *S_CFFT = S->pCfft; +#endif + uint32_t L2 = S->fftLenReal >> 1U; + + /* Calculation of RIFFT of input */ + if (S->ifftFlagR == 1U) + { + /* Real IFFT core process */ + arm_split_rifft_q15 (pSrc, L2, S->pTwiddleAReal, S->pTwiddleBReal, pDst, S->twidCoefRModifier); + + /* Complex IFFT process */ + arm_cfft_q15 (S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR); + + arm_shift_q15(pDst, 1, pDst, S->fftLenReal); + } + else + { + /* Calculation of RFFT of input */ + + /* Complex FFT process */ + arm_cfft_q15 (S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR); + + /* Real FFT core process */ + arm_split_rfft_q15 (pSrc, L2, S->pTwiddleAReal, S->pTwiddleBReal, pDst, S->twidCoefRModifier); + } + +} +#endif + +/** + @} end of RealFFTQ15 group + */ + +/** + @brief Core Real FFT process + @param[in] pSrc points to input buffer + @param[in] fftLen length of FFT + @param[in] pATable points to twiddle Coef A buffer + @param[in] pBTable points to twiddle Coef B buffer + @param[out] pDst points to output buffer + @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table + + @par + The function implements a Real FFT + */ + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_helium_utils.h" +#include "arm_vec_fft.h" + + +ARM_DSP_ATTRIBUTE void arm_split_rfft_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pATable, + const q15_t * pBTable, + q15_t * pDst, + uint32_t modifier) +{ + uint32_t i; /* Loop Counter */ + const q15_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ + q15_t *pOut1 = &pDst[2]; + q15_t *pIn1 = &pSrc[2]; + uint16x8_t offsetIn = { 6, 7, 4, 5, 2, 3, 0, 1 }; + uint16x8_t offsetCoef; + const uint16_t offsetCoefArr[16] = { + 0, 0, 2, 2, 4, 4, 6, 6, + 0, 1, 0, 1, 0, 1, 0, 1 + }; + + offsetCoef = vmulq_n_u16(vld1q_u16(offsetCoefArr), modifier) + vld1q_u16(offsetCoefArr + 8); + offsetIn = vaddq_n_u16(offsetIn, (2 * fftLen - 8)); + + /* Init coefficient pointers */ + pCoefA = &pATable[modifier * 2]; + pCoefB = &pBTable[modifier * 2]; + + const q15_t *pCoefAb, *pCoefBb; + pCoefAb = pCoefA; + pCoefBb = pCoefB; + + pIn1 = &pSrc[2]; + + i = fftLen - 1U; + i = i / 4 + 1; + while (i > 0U) { + q15x8_t in1 = vld1q_s16(pIn1); + q15x8_t in2 = vldrhq_gather_shifted_offset_s16(pSrc, offsetIn); + q15x8_t coefA = vldrhq_gather_shifted_offset_s16(pCoefAb, offsetCoef); + q15x8_t coefB = vldrhq_gather_shifted_offset_s16(pCoefBb, offsetCoef); + + + q15x8_t out = vhaddq_s16(MVE_CMPLX_MULT_FX_AxB(in1, coefA, q15x8_t), + MVE_CMPLX_MULT_FX_AxConjB(coefB, in2, q15x8_t)); + vst1q_s16(pOut1, out); + pOut1 += 8; + + offsetCoef = vaddq_n_u16(offsetCoef, modifier * 8); + offsetIn -= 8; + pIn1 += 8; + i -= 1; + } + + pDst[2 * fftLen] = (pSrc[0] - pSrc[1]) >> 1U; + pDst[2 * fftLen + 1] = 0; + + pDst[0] = (pSrc[0] + pSrc[1]) >> 1U; + pDst[1] = 0; +} +#elif !defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE void arm_split_rfft_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pATable, + const q15_t * pBTable, + q15_t * pDst, + uint32_t modifier) +{ + uint32_t i; /* Loop Counter */ + q31_t outR, outI; /* Temporary variables for output */ + const q15_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ + q15_t *pSrc1, *pSrc2; +#if defined (ARM_MATH_DSP) + q15_t *pD1, *pD2; +#endif + + /* Init coefficient pointers */ + pCoefA = &pATable[modifier * 2]; + pCoefB = &pBTable[modifier * 2]; + + pSrc1 = &pSrc[2]; + pSrc2 = &pSrc[(2U * fftLen) - 2U]; + +#if defined (ARM_MATH_DSP) + + i = 1U; + pD1 = pDst + 2; + pD2 = pDst + (4U * fftLen) - 2; + + for (i = fftLen - 1; i > 0; i--) + { + /* + outR = ( pSrc[2 * i] * pATable[2 * i] + - pSrc[2 * i + 1] * pATable[2 * i + 1] + + pSrc[2 * n - 2 * i] * pBTable[2 * i] + + pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); + + outI = ( pIn[2 * i + 1] * pATable[2 * i] + + pIn[2 * i] * pATable[2 * i + 1] + + pIn[2 * n - 2 * i] * pBTable[2 * i + 1] + - pIn[2 * n - 2 * i + 1] * pBTable[2 * i]) + */ + + +#ifndef ARM_MATH_BIG_ENDIAN + /* pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1] */ + outR = __SMUSD(read_q15x2 (pSrc1), read_q15x2((q15_t *) pCoefA)); +#else + /* -(pSrc[2 * i + 1] * pATable[2 * i + 1] - pSrc[2 * i] * pATable[2 * i]) */ + outR = -(__SMUSD(read_q15x2 (pSrc1), read_q15x2((q15_t *) pCoefA))); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* pSrc[2 * n - 2 * i] * pBTable[2 * i] + pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */ + outR = __SMLAD(read_q15x2 (pSrc2), read_q15x2((q15_t *) pCoefB), outR) >> 16U; + + /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] - pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */ +#ifndef ARM_MATH_BIG_ENDIAN + outI = __SMUSDX(read_q15x2_da (&pSrc2), read_q15x2((q15_t *) pCoefB)); +#else + outI = __SMUSDX(read_q15x2 ((q15_t *) pCoefB), read_q15x2_da (&pSrc2)); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] */ + outI = __SMLADX(read_q15x2_ia (&pSrc1), read_q15x2 ((q15_t *) pCoefA), outI); + + /* write output */ + *pD1++ = (q15_t) outR; + *pD1++ = outI >> 16U; + + /* write complex conjugate output */ + pD2[0] = (q15_t) outR; + pD2[1] = -(outI >> 16U); + pD2 -= 2; + + /* update coefficient pointer */ + pCoefB = pCoefB + (2U * modifier); + pCoefA = pCoefA + (2U * modifier); + } + + pDst[2U * fftLen] = (pSrc[0] - pSrc[1]) >> 1U; + pDst[2U * fftLen + 1U] = 0; + + pDst[0] = (pSrc[0] + pSrc[1]) >> 1U; + pDst[1] = 0; + +#else + + i = 1U; + + while (i < fftLen) + { + /* + outR = ( pSrc[2 * i] * pATable[2 * i] + - pSrc[2 * i + 1] * pATable[2 * i + 1] + + pSrc[2 * n - 2 * i] * pBTable[2 * i] + + pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); + */ + + outR = *pSrc1 * *pCoefA; + outR = outR - (*(pSrc1 + 1) * *(pCoefA + 1)); + outR = outR + (*pSrc2 * *pCoefB); + outR = (outR + (*(pSrc2 + 1) * *(pCoefB + 1))) >> 16; + + /* + outI = ( pIn[2 * i + 1] * pATable[2 * i] + + pIn[2 * i] * pATable[2 * i + 1] + + pIn[2 * n - 2 * i] * pBTable[2 * i + 1] + - pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); + */ + + outI = *pSrc2 * *(pCoefB + 1); + outI = outI - (*(pSrc2 + 1) * *pCoefB); + outI = outI + (*(pSrc1 + 1) * *pCoefA); + outI = outI + (*pSrc1 * *(pCoefA + 1)); + + /* update input pointers */ + pSrc1 += 2U; + pSrc2 -= 2U; + + /* write output */ + pDst[2U * i] = (q15_t) outR; + pDst[2U * i + 1U] = outI >> 16U; + + /* write complex conjugate output */ + pDst[(4U * fftLen) - (2U * i)] = (q15_t) outR; + pDst[((4U * fftLen) - (2U * i)) + 1U] = -(outI >> 16U); + + /* update coefficient pointer */ + pCoefB = pCoefB + (2U * modifier); + pCoefA = pCoefA + (2U * modifier); + + i++; + } + + pDst[2U * fftLen] = (pSrc[0] - pSrc[1]) >> 1; + pDst[2U * fftLen + 1U] = 0; + + pDst[0] = (pSrc[0] + pSrc[1]) >> 1; + pDst[1] = 0; + +#endif /* #if defined (ARM_MATH_DSP) */ +} +#endif /* defined(ARM_MATH_MVEI) */ + +/** + @brief Core Real IFFT process + @param[in] pSrc points to input buffer + @param[in] fftLen length of FFT + @param[in] pATable points to twiddle Coef A buffer + @param[in] pBTable points to twiddle Coef B buffer + @param[out] pDst points to output buffer + @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table + + @par + The function implements a Real IFFT + */ + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_helium_utils.h" +#include "arm_vec_fft.h" + +ARM_DSP_ATTRIBUTE void arm_split_rifft_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pATable, + const q15_t * pBTable, + q15_t * pDst, + uint32_t modifier) +{ + uint32_t i; /* Loop Counter */ + const q15_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ + q15_t *pIn1; + uint16x8_t offset = { 6, 7, 4, 5, 2, 3, 0, 1 }; + uint16x8_t offsetCoef; + int16x8_t conj = { 1, -1, 1, -1, 1, -1, 1, -1 }; /* conjugate */ + const uint16_t offsetCoefArr[16] = { + 0, 0, 2, 2, 4, 4, 6, 6, + 0, 1, 0, 1, 0, 1, 0, 1 + }; + + offsetCoef = vmulq_n_u16(vld1q_u16(offsetCoefArr), modifier) + vld1q_u16(offsetCoefArr + 8); + + offset = vaddq_n_u16(offset, (2 * fftLen - 6)); + + /* Init coefficient pointers */ + pCoefA = &pATable[0]; + pCoefB = &pBTable[0]; + + const q15_t *pCoefAb, *pCoefBb; + pCoefAb = pCoefA; + pCoefBb = pCoefB; + + pIn1 = &pSrc[0]; + + i = fftLen; + i = i / 4; + + while (i > 0U) { + q15x8_t in1 = vld1q_s16(pIn1); + q15x8_t in2 = vldrhq_gather_shifted_offset_s16(pSrc, offset); + q15x8_t coefA = vldrhq_gather_shifted_offset_s16(pCoefAb, offsetCoef); + q15x8_t coefB = vldrhq_gather_shifted_offset_s16(pCoefBb, offsetCoef); + + /* can we avoid the conjugate here ? */ + q15x8_t out = vhaddq_s16(MVE_CMPLX_MULT_FX_AxConjB(in1, coefA, q15x8_t), + vmulq(conj, MVE_CMPLX_MULT_FX_AxB(in2, coefB, q15x8_t))); + + vst1q_s16(pDst, out); + pDst += 8; + + offsetCoef = vaddq_n_u16(offsetCoef, modifier * 8); + offset -= 8; + + pIn1 += 8; + i -= 1; + } +} +#elif !defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE void arm_split_rifft_q15( + q15_t * pSrc, + uint32_t fftLen, + const q15_t * pATable, + const q15_t * pBTable, + q15_t * pDst, + uint32_t modifier) +{ + uint32_t i; /* Loop Counter */ + q31_t outR, outI; /* Temporary variables for output */ + const q15_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ + q15_t *pSrc1, *pSrc2; + q15_t *pDst1 = &pDst[0]; + + pCoefA = &pATable[0]; + pCoefB = &pBTable[0]; + + pSrc1 = &pSrc[0]; + pSrc2 = &pSrc[2 * fftLen]; + + i = fftLen; + while (i > 0U) + { + /* + outR = ( pIn[2 * i] * pATable[2 * i] + + pIn[2 * i + 1] * pATable[2 * i + 1] + + pIn[2 * n - 2 * i] * pBTable[2 * i] + - pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); + + outI = ( pIn[2 * i + 1] * pATable[2 * i] + - pIn[2 * i] * pATable[2 * i + 1] + - pIn[2 * n - 2 * i] * pBTable[2 * i + 1] + - pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); + */ + +#if defined (ARM_MATH_DSP) + +#ifndef ARM_MATH_BIG_ENDIAN + /* pIn[2 * n - 2 * i] * pBTable[2 * i] - pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */ + outR = __SMUSD(read_q15x2(pSrc2), read_q15x2((q15_t *) pCoefB)); +#else + /* -(-pIn[2 * n - 2 * i] * pBTable[2 * i] + pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1])) */ + outR = -(__SMUSD(read_q15x2(pSrc2), read_q15x2((q15_t *) pCoefB))); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] + pIn[2 * n - 2 * i] * pBTable[2 * i] */ + outR = __SMLAD(read_q15x2(pSrc1), read_q15x2 ((q15_t *) pCoefA), outR) >> 16U; + + /* -pIn[2 * n - 2 * i] * pBTable[2 * i + 1] + pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */ + outI = __SMUADX(read_q15x2_da (&pSrc2), read_q15x2((q15_t *) pCoefB)); + + /* pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] */ +#ifndef ARM_MATH_BIG_ENDIAN + outI = __SMLSDX(read_q15x2 ((q15_t *) pCoefA), read_q15x2_ia (&pSrc1), -outI); +#else + outI = __SMLSDX(read_q15x2_ia (&pSrc1), read_q15x2 ((q15_t *) pCoefA), -outI); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* write output */ +#ifndef ARM_MATH_BIG_ENDIAN + write_q15x2_ia (&pDst1, __PKHBT(outR, (outI >> 16U), 16)); +#else + write_q15x2_ia (&pDst1, __PKHBT((outI >> 16U), outR, 16)); +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + +#else /* #if defined (ARM_MATH_DSP) */ + + outR = *pSrc2 * *pCoefB; + outR = outR - (*(pSrc2 + 1) * *(pCoefB + 1)); + outR = outR + (*pSrc1 * *pCoefA); + outR = (outR + (*(pSrc1 + 1) * *(pCoefA + 1))) >> 16; + + outI = *(pSrc1 + 1) * *pCoefA; + outI = outI - (*pSrc1 * *(pCoefA + 1)); + outI = outI - (*pSrc2 * *(pCoefB + 1)); + outI = outI - (*(pSrc2 + 1) * *(pCoefB)); + + /* update input pointers */ + pSrc1 += 2U; + pSrc2 -= 2U; + + /* write output */ + *pDst1++ = (q15_t) outR; + *pDst1++ = (q15_t) (outI >> 16); + +#endif /* #if defined (ARM_MATH_DSP) */ + + /* update coefficient pointer */ + pCoefB = pCoefB + (2 * modifier); + pCoefA = pCoefA + (2 * modifier); + + i--; + } + +} +#endif /* defined(ARM_MATH_MVEI) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_q31.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_q31.c new file mode 100755 index 0000000..963f0a2 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_rfft_q31.c @@ -0,0 +1,481 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_rfft_q31.c + * Description: FFT & RIFFT Q31 process function + * + * $Date: 23 April 2021 + * $Revision: V1.9.0 + * + * Target Processor: Cortex-M and Cortex-A cores + * -------------------------------------------------------------------- */ + +/* + * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "arm_compiler_specific.h" + + +#include "dsp/transform_functions.h" + +/* ---------------------------------------------------------------------- + * Internal functions prototypes + * -------------------------------------------------------------------- */ + +#if !defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE void arm_split_rfft_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pATable, + const q31_t * pBTable, + q31_t * pDst, + uint32_t modifier); + +ARM_DSP_ATTRIBUTE void arm_split_rifft_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pATable, + const q31_t * pBTable, + q31_t * pDst, + uint32_t modifier); +#endif +/** + @addtogroup RealFFTQ31 + @{ + */ + +/** + @brief Processing function for the Q31 RFFT/RIFFT. + @param[in] S points to an instance of the Q31 RFFT/RIFFT structure + @param[in] pSrc points to input buffer (Source buffer is modified by this function) + @param[out] pDst points to output buffer + + @par Input an output formats + Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process. + Hence the output format is different for different RFFT sizes. + The input and output formats for different RFFT sizes and number of bits to upscale are mentioned in the tables below for RFFT and RIFFT: + @par Input and Output formats for RFFT Q31 + +| RFFT Size | Input Format | Output Format | Number of bits to upscale | +| ---------: | ------------: | -------------: | ------------------------: | +| 32 | 1.31 | 6.26 | 5 | +| 64 | 1.31 | 7.25 | 6 | +| 128 | 1.31 | 8.24 | 7 | +| 256 | 1.31 | 9.23 | 8 | +| 512 | 1.31 | 10.22 | 9 | +| 1024 | 1.31 | 11.21 | 10 | +| 2048 | 1.31 | 12.20 | 11 | +| 4096 | 1.31 | 13.19 | 12 | +| 8192 | 1.31 | 14.18 | 13 | + + @par Input and Output formats for RIFFT Q31 + +| RIFFT Size | Input Format | Output Format | Number of bits to upscale | +| ----------: | ------------: | -------------: | ------------------------: | +| 32 | 1.31 | 6.26 | 0 | +| 64 | 1.31 | 7.25 | 0 | +| 128 | 1.31 | 8.24 | 0 | +| 256 | 1.31 | 9.23 | 0 | +| 512 | 1.31 | 10.22 | 0 | +| 1024 | 1.31 | 11.21 | 0 | +| 2048 | 1.31 | 12.20 | 0 | +| 4096 | 1.31 | 13.19 | 0 | +| 8192 | 1.31 | 14.18 | 0 | + + + @par Neon implementation + A temporary buffer is needed + + @code + void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + q31_t *tmp, + uint8_t ifftFlag + ) + @endcode + + @par Size of buffers according to the target architecture and datatype: + They are described on the page \ref transformbuffers "transform buffers". + + */ + +#if defined(ARM_MATH_NEON) +#include "CMSIS_NE10_types.h" +#include "CMSIS_NE10_fft.h" + + +ARM_DSP_ATTRIBUTE void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + const q31_t * pSrc, + q31_t * pDst, + q31_t *tmp, + uint8_t ifftFlag + ) +{ + if (ifftFlag) + { + arm_ne10_fft_c2r_1d_int32_neon (pDst, + pSrc, + S, + 1, + tmp); + } + else + { + arm_ne10_fft_r2c_1d_int32_neon (pDst, + pSrc, + S, + 1, + tmp); + } +} +#else +ARM_DSP_ATTRIBUTE void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst) +{ +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + const arm_cfft_instance_q31 *S_CFFT = &(S->cfftInst); +#else + const arm_cfft_instance_q31 *S_CFFT = S->pCfft; +#endif + uint32_t L2 = S->fftLenReal >> 1U; + + /* Calculation of RIFFT of input */ + if (S->ifftFlagR == 1U) + { + /* Real IFFT core process */ + arm_split_rifft_q31 (pSrc, L2, S->pTwiddleAReal, S->pTwiddleBReal, pDst, S->twidCoefRModifier); + + /* Complex IFFT process */ + arm_cfft_q31 (S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR); + + arm_shift_q31(pDst, 1, pDst, S->fftLenReal); + } + else + { + /* Calculation of RFFT of input */ + + /* Complex FFT process */ + arm_cfft_q31 (S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR); + + /* Real FFT core process */ + arm_split_rfft_q31 (pSrc, L2, S->pTwiddleAReal, S->pTwiddleBReal, pDst, S->twidCoefRModifier); + } + +} + +#endif +/** + @} end of RealFFTQ31 group + */ + +/** + @brief Core Real FFT process + @param[in] pSrc points to input buffer + @param[in] fftLen length of FFT + @param[in] pATable points to twiddle Coef A buffer + @param[in] pBTable points to twiddle Coef B buffer + @param[out] pDst points to output buffer + @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table + */ + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + +#include "arm_helium_utils.h" +#include "arm_vec_fft.h" + + +ARM_DSP_ATTRIBUTE void arm_split_rfft_q31( + q31_t *pSrc, + uint32_t fftLen, + const q31_t *pATable, + const q31_t *pBTable, + q31_t *pDst, + uint32_t modifier) +{ + uint32_t i; /* Loop Counter */ + const q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ + q31_t *pOut1 = &pDst[2]; + q31_t *pIn1 = &pSrc[2]; + uint32x4_t offset = { 2, 3, 0, 1 }; + uint32x4_t offsetCoef = { 0, 1, modifier * 2, modifier * 2 + 1 }; + + offset = offset + (2 * fftLen - 4); + + + /* Init coefficient pointers */ + pCoefA = &pATable[modifier * 2]; + pCoefB = &pBTable[modifier * 2]; + + const q31_t *pCoefAb, *pCoefBb; + pCoefAb = pCoefA; + pCoefBb = pCoefB; + + pIn1 = &pSrc[2]; + + i = fftLen - 1U; + i = i / 2 + 1; + while (i > 0U) { + q31x4_t in1 = vld1q_s32(pIn1); + q31x4_t in2 = vldrwq_gather_shifted_offset_s32(pSrc, offset); + q31x4_t coefA = vldrwq_gather_shifted_offset_s32(pCoefAb, offsetCoef); + q31x4_t coefB = vldrwq_gather_shifted_offset_s32(pCoefBb, offsetCoef); + + q31x4_t out = vhaddq_s32(MVE_CMPLX_MULT_FX_AxB(in1, coefA, q31x4_t), + MVE_CMPLX_MULT_FX_AxConjB(coefB, in2, q31x4_t)); + vst1q(pOut1, out); + pOut1 += 4; + + offsetCoef += modifier * 4; + offset -= 4; + + pIn1 += 4; + i -= 1; + } + + pDst[2 * fftLen] = (pSrc[0] - pSrc[1]) >> 1U; + pDst[2 * fftLen + 1] = 0; + + pDst[0] = (pSrc[0] + pSrc[1]) >> 1U; + pDst[1] = 0; +} +#elif !defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE void arm_split_rfft_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pATable, + const q31_t * pBTable, + q31_t * pDst, + uint32_t modifier) +{ + uint32_t i; /* Loop Counter */ + q31_t outR, outI; /* Temporary variables for output */ + const q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ + q31_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */ + q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[4 * fftLen - 1]; + q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[2 * fftLen - 1]; + + /* Init coefficient pointers */ + pCoefA = &pATable[modifier * 2]; + pCoefB = &pBTable[modifier * 2]; + + i = fftLen - 1U; + + while (i > 0U) + { + /* + outR = ( pSrc[2 * i] * pATable[2 * i] + - pSrc[2 * i + 1] * pATable[2 * i + 1] + + pSrc[2 * n - 2 * i] * pBTable[2 * i] + + pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); + + outI = ( pIn[2 * i + 1] * pATable[2 * i] + + pIn[2 * i] * pATable[2 * i + 1] + + pIn[2 * n - 2 * i] * pBTable[2 * i + 1] + - pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); + */ + + CoefA1 = *pCoefA++; + CoefA2 = *pCoefA; + + /* outR = (pSrc[2 * i] * pATable[2 * i] */ + mult_32x32_keep32_R (outR, *pIn1, CoefA1); + + /* outI = pIn[2 * i] * pATable[2 * i + 1] */ + mult_32x32_keep32_R (outI, *pIn1++, CoefA2); + + /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */ + multSub_32x32_keep32_R (outR, *pIn1, CoefA2); + + /* (pIn[2 * i + 1] * pATable[2 * i] */ + multAcc_32x32_keep32_R (outI, *pIn1++, CoefA1); + + /* pSrc[2 * n - 2 * i] * pBTable[2 * i] */ + multSub_32x32_keep32_R (outR, *pIn2, CoefA2); + CoefB1 = *pCoefB; + + /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */ + multSub_32x32_keep32_R (outI, *pIn2--, CoefB1); + + /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */ + multAcc_32x32_keep32_R (outR, *pIn2, CoefB1); + + /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */ + multSub_32x32_keep32_R (outI, *pIn2--, CoefA2); + + /* write output */ + *pOut1++ = outR; + *pOut1++ = outI; + + /* write complex conjugate output */ + *pOut2-- = -outI; + *pOut2-- = outR; + + /* update coefficient pointer */ + pCoefB = pCoefB + (2 * modifier); + pCoefA = pCoefA + (2 * modifier - 1); + + /* Decrement loop count */ + i--; + } + + pDst[2 * fftLen] = (pSrc[0] - pSrc[1]) >> 1U; + pDst[2 * fftLen + 1] = 0; + + pDst[0] = (pSrc[0] + pSrc[1]) >> 1U; + pDst[1] = 0; +} +#endif /* defined(ARM_MATH_MVEI) */ + +/** + @brief Core Real IFFT process + @param[in] pSrc points to input buffer + @param[in] fftLen length of FFT + @param[in] pATable points to twiddle Coef A buffer + @param[in] pBTable points to twiddle Coef B buffer + @param[out] pDst points to output buffer + @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table + */ + +#if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE) + +ARM_DSP_ATTRIBUTE void arm_split_rifft_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pATable, + const q31_t * pBTable, + q31_t * pDst, + uint32_t modifier) +{ + uint32_t i; /* Loop Counter */ + const q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ + q31_t *pIn1; + uint32x4_t offset = { 2, 3, 0, 1 }; + uint32x4_t offsetCoef = { 0, 1, modifier * 2, modifier * 2 + 1 }; + int32x4_t conj = { 1, -1, 1, -1 }; + + offset = offset + (2 * fftLen - 2); + + /* Init coefficient pointers */ + pCoefA = &pATable[0]; + pCoefB = &pBTable[0]; + + const q31_t *pCoefAb, *pCoefBb; + pCoefAb = pCoefA; + pCoefBb = pCoefB; + + pIn1 = &pSrc[0]; + + i = fftLen; + i = i >> 1; + while (i > 0U) { + q31x4_t in1 = vld1q_s32(pIn1); + q31x4_t in2 = vldrwq_gather_shifted_offset_s32(pSrc, offset); + q31x4_t coefA = vldrwq_gather_shifted_offset_s32(pCoefAb, offsetCoef); + q31x4_t coefB = vldrwq_gather_shifted_offset_s32(pCoefBb, offsetCoef); + + /* can we avoid the conjugate here ? */ + q31x4_t out = vhaddq_s32(MVE_CMPLX_MULT_FX_AxConjB(in1, coefA, q31x4_t), + vmulq_s32(conj, MVE_CMPLX_MULT_FX_AxB(in2, coefB, q31x4_t))); + + vst1q_s32(pDst, out); + pDst += 4; + + offsetCoef += modifier * 4; + offset -= 4; + + pIn1 += 4; + i -= 1; + } +} +#elif !defined(ARM_MATH_NEON) +ARM_DSP_ATTRIBUTE void arm_split_rifft_q31( + q31_t * pSrc, + uint32_t fftLen, + const q31_t * pATable, + const q31_t * pBTable, + q31_t * pDst, + uint32_t modifier) +{ + q31_t outR, outI; /* Temporary variables for output */ + const q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ + q31_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */ + q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[2 * fftLen + 1]; + + pCoefA = &pATable[0]; + pCoefB = &pBTable[0]; + + while (fftLen > 0U) + { + /* + outR = ( pIn[2 * i] * pATable[2 * i] + + pIn[2 * i + 1] * pATable[2 * i + 1] + + pIn[2 * n - 2 * i] * pBTable[2 * i] + - pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); + + outI = ( pIn[2 * i + 1] * pATable[2 * i] + - pIn[2 * i] * pATable[2 * i + 1] + - pIn[2 * n - 2 * i] * pBTable[2 * i + 1] + - pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); + */ + + CoefA1 = *pCoefA++; + CoefA2 = *pCoefA; + + /* outR = (pIn[2 * i] * pATable[2 * i] */ + mult_32x32_keep32_R (outR, *pIn1, CoefA1); + + /* - pIn[2 * i] * pATable[2 * i + 1] */ + mult_32x32_keep32_R (outI, *pIn1++, -CoefA2); + + /* pIn[2 * i + 1] * pATable[2 * i + 1] */ + multAcc_32x32_keep32_R (outR, *pIn1, CoefA2); + + /* pIn[2 * i + 1] * pATable[2 * i] */ + multAcc_32x32_keep32_R (outI, *pIn1++, CoefA1); + + /* pIn[2 * n - 2 * i] * pBTable[2 * i] */ + multAcc_32x32_keep32_R (outR, *pIn2, CoefA2); + CoefB1 = *pCoefB; + + /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */ + multSub_32x32_keep32_R (outI, *pIn2--, CoefB1); + + /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */ + multAcc_32x32_keep32_R (outR, *pIn2, CoefB1); + + /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */ + multAcc_32x32_keep32_R (outI, *pIn2--, CoefA2); + + /* write output */ + *pDst++ = outR; + *pDst++ = outI; + + /* update coefficient pointer */ + pCoefB = pCoefB + (modifier * 2); + pCoefA = pCoefA + (modifier * 2 - 1); + + /* Decrement loop count */ + fftLen--; + } + +} + +#endif /* defined(ARM_MATH_MVEI) */ diff --git a/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_transform_buffer_sizes.c b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_transform_buffer_sizes.c new file mode 100755 index 0000000..00c0805 --- /dev/null +++ b/Middlewares/Third_Party/ARM/ARM.CMSIS-DSP.1.17.1/Source/TransformFunctions/arm_transform_buffer_sizes.c @@ -0,0 +1,346 @@ +#include "dsp/transform_functions.h" + +/** + @ingroup groupTransforms +*/ + +/** + @defgroup TransformBuffers Transform Buffer Sizes + @par + Functions to get the sizes of the buffers in the different transform functions + according to the datatype and target architecture. + + @par + The current architecture for the build is defined in `ARM_MATH_DEFAULT_TARGET_ARCH` + + @note All returned lengths are in real numbers and never in complex. So, for a complex buffer of S samples, the + returned length will be 2*S. + +*/ + +/** + @ingroup TransformBuffers +*/ + +/** + @defgroup CFFTBuffers Buffer Sizes for CFFT +*/ + + + +/** + @addtogroup CFFTBuffers + @{ +*/ + +/** + * @brief Calculate required length for the temporary buffer + * @param[in] arch Target architecture identification + * @param[in] dt Data type of the input data + * @param[in] nb_samples Number of samples + * @param[in] buf_id Identification for the temporary buffer + * @return Length in datatype elements (real numbers) for the temporary buffer + * + * @note 0 means not applicable (temporary buffer not needed) + * @note -1 means error : configuration not supported + */ +int32_t arm_cfft_tmp_buffer_size(arm_math_target_arch arch,arm_math_datatype dt, + uint32_t nb_samples, + uint32_t buf_id) +{ + if (arch == ARM_MATH_NEON_ARCH) + { + if (buf_id != 1) + { + return 0; + } + switch(dt) + { + case ARM_MATH_F16: + /* Return values in float hence factor 2 */ + return(nb_samples * 2U); + case ARM_MATH_F32: + /* Return values in float hence factor 2 */ + return(nb_samples * 2U); + case ARM_MATH_Q31: + /* Return values in float hence factor 2 */ + return(nb_samples * 2U); + case ARM_MATH_Q15: + /* Return values in float hence factor 2 */ + return(nb_samples * 2U); + default: + return(0); + } + } + else + { + return(0); + } +} + +/** + * @brief Calculate required length for the output buffer + * @param[in] arch Target architecture identification + * @param[in] dt Data type of the input data + * @param[in] nb_samples Number of samples in the input data + * @return Length in datatype elements (real numbers) for the output buffer + * + * @note 0 means not applicable (temporary buffer not needed) + * @note -1 means error : configuration not supported + */ +int32_t arm_cfft_output_buffer_size(arm_math_target_arch arch,arm_math_datatype dt, + uint32_t nb_samples) +{ + (void)arch; + switch(dt) + { + default: + return(nb_samples * 2U); + } +} + +/** + * @brief Calculate required length for the output buffer + * @param[in] arch Target architecture identification + * @param[in] dt Data type of the input data + * @param[in] nb_samples Number of samples in the input data + * @return Length in datatype elements (real numbers) for the output buffer + * + * @note 0 means not applicable (temporary buffer not needed) + * @note -1 means error : configuration not supported + */ +int32_t arm_cifft_output_buffer_size(arm_math_target_arch arch,arm_math_datatype dt, + uint32_t nb_samples) +{ + (void)arch; + switch(dt) + { + default: + return(nb_samples * 2U); + } +} + +/** +* @} end of CFFTBuffers group +*/ + +/** + @ingroup TransformBuffers +*/ + +/** + @defgroup RFFTBuffers Buffer Sizes for RFFT +*/ + + +/** + @addtogroup RFFTBuffers + @{ +*/ + +/** + * @brief Calculate required length for the temporary buffer for both RFFT and RIFFT + * @param[in] arch Target architecture identification + * @param[in] dt Data type of the input data + * @param[in] nb_samples Number of samples in the input data + * @param[in] buf_id Identification for the temporary buffer + * @return Length in datatype elements (real numbers) for the temporary buffer + * + * @note 0 means not applicable (temporary buffer not needed) + * @note -1 means error : configuration not supported + */ +int32_t arm_rfft_tmp_buffer_size(arm_math_target_arch arch,arm_math_datatype dt, + uint32_t nb_samples, + uint32_t buf_id) +{ + switch(dt) + { + case ARM_MATH_F32: + case ARM_MATH_F16: + if (arch == ARM_MATH_NEON_ARCH) + { + if (buf_id != 1) + { + return 0; + } + return(nb_samples); + } + else + { + return 0; + } + break; + case ARM_MATH_Q31: + case ARM_MATH_Q15: + if (arch == ARM_MATH_NEON_ARCH) + { + if (buf_id != 1) + { + return 0; + } + return(2*nb_samples); + } + else + { + return 0; + } + break; + default: + return(0); + } +} + +/** + * @brief Calculate required length for the output buffer + * @param[in] arch Target architecture identification + * @param[in] dt Data type of the input data + * @param[in] nb_samples Number of samples in the input data + * @return Length in datatype elements (real numbers) for the output buffer + * + * @note 0 means not applicable (temporary buffer not needed) + * @note -1 means error : configuration not supported + */ +int32_t arm_rfft_output_buffer_size(arm_math_target_arch arch,arm_math_datatype dt, + uint32_t nb_samples) +{ + switch(dt) + { + case ARM_MATH_F64: + case ARM_MATH_F32: + case ARM_MATH_F16: + return(nb_samples); + break; + case ARM_MATH_Q31: + case ARM_MATH_Q15: + if (arch == ARM_MATH_NEON_ARCH) + { + return(nb_samples+2); + } + else if (arch == ARM_MATH_HELIUM_ARCH) + { + return(nb_samples+2); + } + else + { + return(2*nb_samples); + } + + break; + default: + return 0; + } +} + +/** + * @brief Calculate required length for the input buffer + * @param[in] arch Target architecture identification + * @param[in] dt Data type of the input data + * @param[in] nb_samples RFFT length in samples + * @return Length in datatype elements (real numbers) for the input buffer + * + * @note 0 means not applicable (temporary buffer not needed) + * @note -1 means error : configuration not supported + */ +int32_t arm_rifft_input_buffer_size(arm_math_target_arch arch,arm_math_datatype dt, + uint32_t nb_samples) +{ + (void)arch; + switch(dt) + { + case ARM_MATH_F64: + case ARM_MATH_F32: + case ARM_MATH_F16: + return(nb_samples); + break; + case ARM_MATH_Q31: + case ARM_MATH_Q15: + return(nb_samples+2); + break; + default: + return 0; + } +} + +/** +* @} end of RFFTBuffers group +*/ + +/** + @ingroup TransformBuffers +*/ + +/** + @defgroup MFCCBuffers Buffer Sizes for MFCC +*/ + + +/** + @addtogroup MFCCBuffers + @{ +*/ + +/** + * @brief Calculate required length for the temporary buffer + * @param[in] arch Target architecture identification + * @param[in] dt Data type of the input data + * @param[in] nb_samples Number of samples in the input data + * @param[in] buf_id Identification for the temporary buffer + * @param[in] use_cfft 1 if implementastion uses CFFT, 0 if RFFT + * @return Length in datatype elements (real numbers) for the temporary buffer + * + * @note 0 means not applicable (temporary buffer not needed) + * @note -1 means error : configuration not supported + * @note The define `ARM_MFCC_USE_CFFT` can be checked to know the current MFCC mode (CFFT or RFFT) for the build + */ +int32_t arm_mfcc_tmp_buffer_size(arm_math_target_arch arch, + arm_math_datatype dt, + uint32_t nb_samples, + uint32_t buf_id, + uint32_t use_cfft) +{ + if (arch == ARM_MATH_NEON_ARCH) + { + if (use_cfft==1) + { + // Neon implementation is forcing the RFFT mode + // So an error is returned for this configuration + return(-1); + } + + if ((buf_id != 1) && (buf_id != 2)) + { + return 0; + } + } + else + { + if (buf_id != 1) + { + return 0; + } + } + + + switch(buf_id) + { + case 1: + if (use_cfft == 1) + { + return(arm_cfft_output_buffer_size(arch,dt, nb_samples)); + } + else + { + return(arm_rfft_output_buffer_size(arch,dt, nb_samples)); + } + case 2: + return(arm_rfft_tmp_buffer_size(arch,dt, nb_samples, 1)); + default: + return(0); + } + + +} + +/** +* @} end of MFCCBuffers group +*/
\ No newline at end of file |
