Compare commits

...

1 Commits

Author SHA1 Message Date
Daniel Agar 9824c6b4ae [WIP] sliding DFT 2022-01-12 20:45:16 -05:00
22 changed files with 495 additions and 87931 deletions
+18 -6
View File
@@ -6,10 +6,22 @@ uint32 device_id # unique device ID for the sensor that does not change
float32 sensor_sample_rate_hz
float32 resolution_hz
float32[3] peak_frequencies_x # x axis peak frequencies
float32[3] peak_frequencies_y # y axis peak frequencies
float32[3] peak_frequencies_z # z axis peak frequencies
float32[5] peak_frequencies_x # x axis peak frequencies
float32[5] peak_frequencies_y # y axis peak frequencies
float32[5] peak_frequencies_z # z axis peak frequencies
float32[3] peak_snr_x # x axis peak SNR
float32[3] peak_snr_y # y axis peak SNR
float32[3] peak_snr_z # z axis peak SNR
float32[5] peak_snr_x # x axis peak SNR
float32[5] peak_snr_y # y axis peak SNR
float32[5] peak_snr_z # z axis peak SNR
float32[5] peak_frequencies_x_raw# x axis peak frequencies
float32[5] peak_frequencies_y_raw # y axis peak frequencies
float32[5] peak_frequencies_z_raw # z axis peak frequencies
float32[5] peak_magnitude_x # x axis peak frequencies magnitude
float32[5] peak_magnitude_y # y axis peak frequencies magnitude
float32[5] peak_magnitude_z # z axis peak frequencies magnitude
float32[3] total_energy
@@ -15,14 +15,15 @@ ver all
param set IMU_GYRO_RATEMAX 1000
param set IMU_GYRO_FFT_EN 1
param set IMU_GYRO_FFT_MIN 10
param set IMU_GYRO_FFT_MAX 1000
param set IMU_GYRO_FFT_MIN 1
param set IMU_GYRO_FFT_MAX 500
param set IMU_GYRO_FFT_LEN 512
param set IMU_GYRO_FFT_SNR 10
# dynamic notches ESC/FFT/both
#param set IMU_GYRO_DNF_EN 1
#param set IMU_GYRO_DNF_EN 2
param set IMU_GYRO_DNF_EN 3
param set IMU_GYRO_DNF_EN 2
#param set IMU_GYRO_DNF_EN 3
# test values
param set IMU_GYRO_CUTOFF 60
-120
View File
@@ -1,120 +0,0 @@
---
Checks: '*,
-android*,
-bugprone-integer-division,
-cert-dcl50-cpp,
-cert-env33-c,
-cert-err34-c,
-cert-err58-cpp,
-cert-msc30-c,
-cert-msc50-cpp,
-cert-flp30-c,
-clang-analyzer-core.CallAndMessage,
-clang-analyzer-core.NullDereference,
-clang-analyzer-core.UndefinedBinaryOperatorResult,
-clang-analyzer-core.uninitialized.Assign,
-clang-analyzer-core.VLASize,
-clang-analyzer-cplusplus.NewDelete,
-clang-analyzer-cplusplus.NewDeleteLeaks,
-clang-analyzer-deadcode.DeadStores,
-clang-analyzer-optin.cplusplus.VirtualCall,
-clang-analyzer-optin.performance.Padding,
-clang-analyzer-security.FloatLoopCounter,
-clang-analyzer-security.insecureAPI.strcpy,
-clang-analyzer-unix.API,
-clang-analyzer-unix.cstring.BadSizeArg,
-clang-analyzer-unix.Malloc,
-clang-analyzer-unix.MallocSizeof,
-cppcoreguidelines-c-copy-assignment-signature,
-cppcoreguidelines-interfaces-global-init,
-cppcoreguidelines-no-malloc,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-const-cast,
-cppcoreguidelines-pro-type-cstyle-cast,
-cppcoreguidelines-pro-type-member-init,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-special-member-functions,
-fuchsia-default-arguments,
-fuchsia-overloaded-operator,
-google-build-using-namespace,
-google-explicit-constructor,
-google-global-names-in-headers,
-google-readability-braces-around-statements,
-google-readability-casting,
-google-readability-function-size,
-google-readability-namespace-comments,
-google-readability-todo,
-google-runtime-int,
-google-runtime-references,
-hicpp-braces-around-statements,
-hicpp-deprecated-headers,
-hicpp-explicit-conversions,
-hicpp-function-size,
-hicpp-member-init,
-hicpp-no-array-decay,
-hicpp-no-assembler,
-hicpp-no-malloc,
-hicpp-signed-bitwise,
-hicpp-special-member-functions,
-hicpp-use-auto,
-hicpp-use-equals-default,
-hicpp-use-equals-delete,
-hicpp-use-override,
-hicpp-vararg,
-llvm-header-guard,
-llvm-include-order,
-llvm-namespace-comment,
-misc-incorrect-roundings,
-misc-macro-parentheses,
-misc-misplaced-widening-cast,
-misc-redundant-expression,
-misc-unconventional-assign-operator,
-misc-unused-parameters,
-modernize-deprecated-headers,
-modernize-loop-convert,
-modernize-pass-by-value,
-modernize-return-braced-init-list,
-modernize-use-auto,
-modernize-use-bool-literals,
-modernize-use-default-member-init,
-modernize-use-emplace,
-modernize-use-equals-default,
-modernize-use-equals-delete,
-modernize-use-override,
-modernize-use-using,
-performance-inefficient-string-concatenation,
-performance-unnecessary-value-param,
-readability-avoid-const-params-in-decls,
-readability-braces-around-statements,
-readability-container-size-empty,
-readability-delete-null-pointer,
-readability-else-after-return,
-readability-function-size,
-readability-implicit-bool-cast,
-readability-implicit-bool-conversion,
-readability-inconsistent-declaration-parameter-name,
-readability-named-parameter,
-readability-non-const-parameter,
-readability-redundant-control-flow,
-readability-redundant-declaration,
-readability-redundant-member-init,
-readability-simplify-boolean-expr,
-readability-static-accessed-through-instance,
-readability-static-definition-in-anonymous-namespace,
'
WarningsAsErrors: '*'
CheckOptions:
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: google-readability-function-size.BranchThreshold
value: '600'
- key: google-readability-function-size.LineThreshold
value: '4000'
- key: google-readability-function-size.StatementThreshold
value: '4000'
...
@@ -1,283 +0,0 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.1.0
* @date 09. October 2018
******************************************************************************/
/*
* Copyright (c) 2009-2018 Arm Limited. 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.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* Arm Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* Arm Compiler 6.6 LTM (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
#include "cmsis_armclang_ltm.h"
/*
* Arm Compiler above 6.10.1 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#include <cmsis_iccarm.h>
/*
* TI Arm Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
/*
* TASKING Compiler
*/
#elif defined ( __TASKING__ )
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */
File diff suppressed because it is too large Load Diff
@@ -1,517 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_common_tables.h
* Description: Extern declaration for common tables
*
* $Date: 27. January 2017
* $Revision: V.1.5.1
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2017 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.
*/
#ifndef _ARM_COMMON_TABLES_H
#define _ARM_COMMON_TABLES_H
#include "arm_math.h"
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_FFT_ALLOW_TABLES)
/* Double Precision Float CFFT twiddles */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREV_1024)
extern const uint16_t armBitRevTable[1024];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_16)
extern const uint64_t twiddleCoefF64_16[32];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_32)
extern const uint64_t twiddleCoefF64_32[64];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_64)
extern const uint64_t twiddleCoefF64_64[128];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_128)
extern const uint64_t twiddleCoefF64_128[256];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_256)
extern const uint64_t twiddleCoefF64_256[512];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_512)
extern const uint64_t twiddleCoefF64_512[1024];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_1024)
extern const uint64_t twiddleCoefF64_1024[2048];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_2048)
extern const uint64_t twiddleCoefF64_2048[4096];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F64_4096)
extern const uint64_t twiddleCoefF64_4096[8192];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_16)
extern const float32_t twiddleCoef_16[32];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_32)
extern const float32_t twiddleCoef_32[64];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_64)
extern const float32_t twiddleCoef_64[128];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_128)
extern const float32_t twiddleCoef_128[256];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_256)
extern const float32_t twiddleCoef_256[512];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_512)
extern const float32_t twiddleCoef_512[1024];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_1024)
extern const float32_t twiddleCoef_1024[2048];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_2048)
extern const float32_t twiddleCoef_2048[4096];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_F32_4096)
extern const float32_t twiddleCoef_4096[8192];
#define twiddleCoef twiddleCoef_4096
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_16)
extern const q31_t twiddleCoef_16_q31[24];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_32)
extern const q31_t twiddleCoef_32_q31[48];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_64)
extern const q31_t twiddleCoef_64_q31[96];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_128)
extern const q31_t twiddleCoef_128_q31[192];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_256)
extern const q31_t twiddleCoef_256_q31[384];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_512)
extern const q31_t twiddleCoef_512_q31[768];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_1024)
extern const q31_t twiddleCoef_1024_q31[1536];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_2048)
extern const q31_t twiddleCoef_2048_q31[3072];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q31_4096)
extern const q31_t twiddleCoef_4096_q31[6144];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_16)
extern const q15_t twiddleCoef_16_q15[24];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_32)
extern const q15_t twiddleCoef_32_q15[48];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_64)
extern const q15_t twiddleCoef_64_q15[96];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_128)
extern const q15_t twiddleCoef_128_q15[192];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_256)
extern const q15_t twiddleCoef_256_q15[384];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_512)
extern const q15_t twiddleCoef_512_q15[768];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_1024)
extern const q15_t twiddleCoef_1024_q15[1536];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_2048)
extern const q15_t twiddleCoef_2048_q15[3072];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_Q15_4096)
extern const q15_t twiddleCoef_4096_q15[6144];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
/* Double Precision Float RFFT twiddles */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_32)
extern const uint64_t twiddleCoefF64_rfft_32[32];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_64)
extern const uint64_t twiddleCoefF64_rfft_64[64];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_128)
extern const uint64_t twiddleCoefF64_rfft_128[128];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_256)
extern const uint64_t twiddleCoefF64_rfft_256[256];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_512)
extern const uint64_t twiddleCoefF64_rfft_512[512];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_1024)
extern const uint64_t twiddleCoefF64_rfft_1024[1024];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_2048)
extern const uint64_t twiddleCoefF64_rfft_2048[2048];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_4096)
extern const uint64_t twiddleCoefF64_rfft_4096[4096];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_32)
extern const float32_t twiddleCoef_rfft_32[32];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_64)
extern const float32_t twiddleCoef_rfft_64[64];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_128)
extern const float32_t twiddleCoef_rfft_128[128];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_256)
extern const float32_t twiddleCoef_rfft_256[256];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_512)
extern const float32_t twiddleCoef_rfft_512[512];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_1024)
extern const float32_t twiddleCoef_rfft_1024[1024];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_2048)
extern const float32_t twiddleCoef_rfft_2048[2048];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_4096)
extern const float32_t twiddleCoef_rfft_4096[4096];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
/* Double precision floating-point bit reversal tables */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_16)
#define ARMBITREVINDEXTABLEF64_16_TABLE_LENGTH ((uint16_t)12)
extern const uint16_t armBitRevIndexTableF64_16[ARMBITREVINDEXTABLEF64_16_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_32)
#define ARMBITREVINDEXTABLEF64_32_TABLE_LENGTH ((uint16_t)24)
extern const uint16_t armBitRevIndexTableF64_32[ARMBITREVINDEXTABLEF64_32_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_64)
#define ARMBITREVINDEXTABLEF64_64_TABLE_LENGTH ((uint16_t)56)
extern const uint16_t armBitRevIndexTableF64_64[ARMBITREVINDEXTABLEF64_64_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_128)
#define ARMBITREVINDEXTABLEF64_128_TABLE_LENGTH ((uint16_t)112)
extern const uint16_t armBitRevIndexTableF64_128[ARMBITREVINDEXTABLEF64_128_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_256)
#define ARMBITREVINDEXTABLEF64_256_TABLE_LENGTH ((uint16_t)240)
extern const uint16_t armBitRevIndexTableF64_256[ARMBITREVINDEXTABLEF64_256_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_512)
#define ARMBITREVINDEXTABLEF64_512_TABLE_LENGTH ((uint16_t)480)
extern const uint16_t armBitRevIndexTableF64_512[ARMBITREVINDEXTABLEF64_512_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_1024)
#define ARMBITREVINDEXTABLEF64_1024_TABLE_LENGTH ((uint16_t)992)
extern const uint16_t armBitRevIndexTableF64_1024[ARMBITREVINDEXTABLEF64_1024_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_2048)
#define ARMBITREVINDEXTABLEF64_2048_TABLE_LENGTH ((uint16_t)1984)
extern const uint16_t armBitRevIndexTableF64_2048[ARMBITREVINDEXTABLEF64_2048_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT64_4096)
#define ARMBITREVINDEXTABLEF64_4096_TABLE_LENGTH ((uint16_t)4032)
extern const uint16_t armBitRevIndexTableF64_4096[ARMBITREVINDEXTABLEF64_4096_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
/* floating-point bit reversal tables */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_16)
#define ARMBITREVINDEXTABLE_16_TABLE_LENGTH ((uint16_t)20)
extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE_16_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_32)
#define ARMBITREVINDEXTABLE_32_TABLE_LENGTH ((uint16_t)48)
extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE_32_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_64)
#define ARMBITREVINDEXTABLE_64_TABLE_LENGTH ((uint16_t)56)
extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE_64_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_128)
#define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208)
extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_256)
#define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440)
extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_512)
#define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448)
extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_1024)
#define ARMBITREVINDEXTABLE_1024_TABLE_LENGTH ((uint16_t)1800)
extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE_1024_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_2048)
#define ARMBITREVINDEXTABLE_2048_TABLE_LENGTH ((uint16_t)3808)
extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE_2048_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FLT_4096)
#define ARMBITREVINDEXTABLE_4096_TABLE_LENGTH ((uint16_t)4032)
extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE_4096_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
/* fixed-point bit reversal tables */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_16)
#define ARMBITREVINDEXTABLE_FIXED_16_TABLE_LENGTH ((uint16_t)12)
extern const uint16_t armBitRevIndexTable_fixed_16[ARMBITREVINDEXTABLE_FIXED_16_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_32)
#define ARMBITREVINDEXTABLE_FIXED_32_TABLE_LENGTH ((uint16_t)24)
extern const uint16_t armBitRevIndexTable_fixed_32[ARMBITREVINDEXTABLE_FIXED_32_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_64)
#define ARMBITREVINDEXTABLE_FIXED_64_TABLE_LENGTH ((uint16_t)56)
extern const uint16_t armBitRevIndexTable_fixed_64[ARMBITREVINDEXTABLE_FIXED_64_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_128)
#define ARMBITREVINDEXTABLE_FIXED_128_TABLE_LENGTH ((uint16_t)112)
extern const uint16_t armBitRevIndexTable_fixed_128[ARMBITREVINDEXTABLE_FIXED_128_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_256)
#define ARMBITREVINDEXTABLE_FIXED_256_TABLE_LENGTH ((uint16_t)240)
extern const uint16_t armBitRevIndexTable_fixed_256[ARMBITREVINDEXTABLE_FIXED_256_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_512)
#define ARMBITREVINDEXTABLE_FIXED_512_TABLE_LENGTH ((uint16_t)480)
extern const uint16_t armBitRevIndexTable_fixed_512[ARMBITREVINDEXTABLE_FIXED_512_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_1024)
#define ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH ((uint16_t)992)
extern const uint16_t armBitRevIndexTable_fixed_1024[ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_2048)
#define ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH ((uint16_t)1984)
extern const uint16_t armBitRevIndexTable_fixed_2048[ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_BITREVIDX_FXT_4096)
#define ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH ((uint16_t)4032)
extern const uint16_t armBitRevIndexTable_fixed_4096[ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_REALCOEF_F32)
extern const float32_t realCoefA[8192];
extern const float32_t realCoefB[8192];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_REALCOEF_Q31)
extern const q31_t realCoefAQ31[8192];
extern const q31_t realCoefBQ31[8192];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_REALCOEF_Q15)
extern const q15_t realCoefAQ15[8192];
extern const q15_t realCoefBQ15[8192];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_F32_128)
extern const float32_t Weights_128[256];
extern const float32_t cos_factors_128[128];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_F32_512)
extern const float32_t Weights_512[1024];
extern const float32_t cos_factors_512[512];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_F32_2048)
extern const float32_t Weights_2048[4096];
extern const float32_t cos_factors_2048[2048];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_F32_8192)
extern const float32_t Weights_8192[16384];
extern const float32_t cos_factors_8192[8192];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_Q15_128)
extern const q15_t WeightsQ15_128[256];
extern const q15_t cos_factorsQ15_128[128];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_Q15_512)
extern const q15_t WeightsQ15_512[1024];
extern const q15_t cos_factorsQ15_512[512];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_Q15_2048)
extern const q15_t WeightsQ15_2048[4096];
extern const q15_t cos_factorsQ15_2048[2048];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_Q15_8192)
extern const q15_t WeightsQ15_8192[16384];
extern const q15_t cos_factorsQ15_8192[8192];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_Q31_128)
extern const q31_t WeightsQ31_128[256];
extern const q31_t cos_factorsQ31_128[128];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_Q31_512)
extern const q31_t WeightsQ31_512[1024];
extern const q31_t cos_factorsQ31_512[512];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_Q31_2048)
extern const q31_t WeightsQ31_2048[4096];
extern const q31_t cos_factorsQ31_2048[2048];
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || defined(ARM_TABLE_DCT4_Q31_8192)
extern const q31_t WeightsQ31_8192[16384];
extern const q31_t cos_factorsQ31_8192[8192];
#endif
#endif /* if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_FFT_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_FAST_ALLOW_TABLES)
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FAST_TABLES) || defined(ARM_TABLE_RECIP_Q15)
extern const q15_t armRecipTableQ15[64];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) defined(ARM_ALL_FAST_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FAST_TABLES) || defined(ARM_TABLE_RECIP_Q31)
extern const q31_t armRecipTableQ31[64];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) defined(ARM_ALL_FAST_TABLES) */
/* Tables for Fast Math Sine and Cosine */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FAST_TABLES) || defined(ARM_TABLE_SIN_F32)
extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) defined(ARM_ALL_FAST_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FAST_TABLES) || defined(ARM_TABLE_SIN_Q31)
extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) defined(ARM_ALL_FAST_TABLES) */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FAST_TABLES) || defined(ARM_TABLE_SIN_Q15)
extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) defined(ARM_ALL_FAST_TABLES) */
#if defined(ARM_MATH_MVEI)
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FAST_TABLES) || defined(ARM_TABLE_FAST_SQRT_Q31_MVE)
extern const q31_t sqrtTable_Q31[256];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) defined(ARM_ALL_FAST_TABLES) */
#endif
#if defined(ARM_MATH_MVEI)
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FAST_TABLES) || defined(ARM_TABLE_FAST_SQRT_Q15_MVE)
extern const q15_t sqrtTable_Q15[256];
#endif /* !defined(ARM_DSP_CONFIG_TABLES) defined(ARM_ALL_FAST_TABLES) */
#endif
#endif /* if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_FAST_TABLES) */
#if (defined(ARM_MATH_MVEF) || defined(ARM_MATH_HELIUM)) && !defined(ARM_MATH_AUTOVECTORIZE)
extern const float32_t exp_tab[8];
extern const float32_t __logf_lut_f32[8];
#endif /* (defined(ARM_MATH_MVEF) || defined(ARM_MATH_HELIUM)) && !defined(ARM_MATH_AUTOVECTORIZE) */
#if (defined(ARM_MATH_MVEI) || defined(ARM_MATH_HELIUM))
extern const unsigned char hwLUT[256];
#endif /* (defined(ARM_MATH_MVEI) || defined(ARM_MATH_HELIUM)) */
#endif /* ARM_COMMON_TABLES_H */
@@ -1,76 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_const_structs.h
* Description: Constant structs that are initialized for user convenience.
* For example, some can be given as arguments to the arm_cfft_f32() function.
*
* $Date: 27. January 2017
* $Revision: V.1.5.1
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2017 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.
*/
#ifndef _ARM_CONST_STRUCTS_H
#define _ARM_CONST_STRUCTS_H
#include "arm_math.h"
#include "arm_common_tables.h"
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len16;
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len32;
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len64;
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len128;
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len256;
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len512;
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len1024;
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len2048;
extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len4096;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096;
#endif
File diff suppressed because it is too large Load Diff
@@ -1,192 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_mult_q15.c
* Description: Q15 vector multiplication
*
* $Date: 18. March 2019
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-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 "arm_math.h"
/**
@ingroup groupMath
*/
/**
@addtogroup BasicMult
@{
*/
/**
@brief Q15 vector multiplication
@param[in] pSrcA points to first input vector
@param[in] pSrcB points to second input vector
@param[out] pDst points to output vector
@param[in] blockSize number of samples in each vector
@return none
@par Scaling and Overflow Behavior
The function uses saturating arithmetic.
Results outside of the allowable Q15 range [0x8000 0x7FFF] are saturated.
*/
#if defined(ARM_MATH_MVEI)
#include "arm_helium_utils.h"
void arm_mult_q15(
const q15_t * pSrcA,
const q15_t * pSrcB,
q15_t * pDst,
uint32_t blockSize)
{
uint32_t blkCnt; /* loop counters */
q15x8_t vecA, vecB;
/* Compute 8 outputs at a time */
blkCnt = blockSize >> 3;
while (blkCnt > 0U)
{
/*
* C = A * B
* Multiply the inputs and then store the results in the destination buffer.
*/
vecA = vld1q(pSrcA);
vecB = vld1q(pSrcB);
vst1q(pDst, vqdmulhq(vecA, vecB));
/*
* Decrement the blockSize loop counter
*/
blkCnt--;
/*
* advance vector source and destination pointers
*/
pSrcA += 8;
pSrcB += 8;
pDst += 8;
}
/*
* tail
*/
blkCnt = blockSize & 7;
if (blkCnt > 0U)
{
mve_pred16_t p0 = vctp16q(blkCnt);
vecA = vld1q(pSrcA);
vecB = vld1q(pSrcB);
vstrhq_p(pDst, vqdmulhq(vecA, vecB), p0);
}
}
#else
void arm_mult_q15(
const q15_t * pSrcA,
const q15_t * pSrcB,
q15_t * pDst,
uint32_t blockSize)
{
uint32_t blkCnt; /* Loop counter */
#if defined (ARM_MATH_LOOPUNROLL)
#if defined (ARM_MATH_DSP)
q31_t inA1, inA2, inB1, inB2; /* Temporary input variables */
q15_t out1, out2, out3, out4; /* Temporary output variables */
q31_t mul1, mul2, mul3, mul4; /* Temporary variables */
#endif
/* Loop unrolling: Compute 4 outputs at a time */
blkCnt = blockSize >> 2U;
while (blkCnt > 0U)
{
/* C = A * B */
#if defined (ARM_MATH_DSP)
/* read 2 samples at a time from sourceA */
inA1 = read_q15x2_ia ((q15_t **) &pSrcA);
/* read 2 samples at a time from sourceB */
inB1 = read_q15x2_ia ((q15_t **) &pSrcB);
/* read 2 samples at a time from sourceA */
inA2 = read_q15x2_ia ((q15_t **) &pSrcA);
/* read 2 samples at a time from sourceB */
inB2 = read_q15x2_ia ((q15_t **) &pSrcB);
/* multiply mul = sourceA * sourceB */
mul1 = (q31_t) ((q15_t) (inA1 >> 16) * (q15_t) (inB1 >> 16));
mul2 = (q31_t) ((q15_t) (inA1 ) * (q15_t) (inB1 ));
mul3 = (q31_t) ((q15_t) (inA2 >> 16) * (q15_t) (inB2 >> 16));
mul4 = (q31_t) ((q15_t) (inA2 ) * (q15_t) (inB2 ));
/* saturate result to 16 bit */
out1 = (q15_t) __SSAT(mul1 >> 15, 16);
out2 = (q15_t) __SSAT(mul2 >> 15, 16);
out3 = (q15_t) __SSAT(mul3 >> 15, 16);
out4 = (q15_t) __SSAT(mul4 >> 15, 16);
/* store result to destination */
#ifndef ARM_MATH_BIG_ENDIAN
write_q15x2_ia (&pDst, __PKHBT(out2, out1, 16));
write_q15x2_ia (&pDst, __PKHBT(out4, out3, 16));
#else
write_q15x2_ia (&pDst, __PKHBT(out1, out2, 16));
write_q15x2_ia (&pDst, __PKHBT(out3, out4, 16));
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
#else
*pDst++ = (q15_t) __SSAT((((q31_t) (*pSrcA++) * (*pSrcB++)) >> 15), 16);
*pDst++ = (q15_t) __SSAT((((q31_t) (*pSrcA++) * (*pSrcB++)) >> 15), 16);
*pDst++ = (q15_t) __SSAT((((q31_t) (*pSrcA++) * (*pSrcB++)) >> 15), 16);
*pDst++ = (q15_t) __SSAT((((q31_t) (*pSrcA++) * (*pSrcB++)) >> 15), 16);
#endif
/* Decrement loop counter */
blkCnt--;
}
/* Loop unrolling: Compute remaining outputs */
blkCnt = blockSize % 0x4U;
#else
/* Initialize blkCnt with number of samples */
blkCnt = blockSize;
#endif /* #if defined (ARM_MATH_LOOPUNROLL) */
while (blkCnt > 0U)
{
/* C = A * B */
/* Multiply inputs and store result in destination buffer. */
*pDst++ = (q15_t) __SSAT((((q31_t) (*pSrcA++) * (*pSrcB++)) >> 15), 16);
/* Decrement loop counter */
blkCnt--;
}
}
#endif /* defined(ARM_MATH_MVEI) */
/**
@} end of BasicMult group
*/
File diff suppressed because it is too large Load Diff
@@ -1,663 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_const_structs.c
* Description: Constant structs that are initialized for user convenience.
* For example, some can be given as arguments to the arm_cfft_f32() or arm_rfft_f32() functions.
*
* $Date: 27. January 2017
* $Revision: V.1.5.1
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2017 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_math.h"
#include "arm_const_structs.h"
/*
ALLOW TABLE is true when config table is enabled and the Tramsform folder is included
for compilation.
*/
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_FFT_ALLOW_TABLES)
/* Floating-point structs */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_16) && defined(ARM_TABLE_BITREVIDX_FLT64_16))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len16 = {
16, (const float64_t *)twiddleCoefF64_16, armBitRevIndexTableF64_16, ARMBITREVINDEXTABLEF64_16_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_32) && defined(ARM_TABLE_BITREVIDX_FLT64_32))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len32 = {
32, (const float64_t *)twiddleCoefF64_32, armBitRevIndexTableF64_32, ARMBITREVINDEXTABLEF64_32_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_64) && defined(ARM_TABLE_BITREVIDX_FLT64_64))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len64 = {
64, (const float64_t *)twiddleCoefF64_64, armBitRevIndexTableF64_64, ARMBITREVINDEXTABLEF64_64_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_128) && defined(ARM_TABLE_BITREVIDX_FLT64_128))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len128 = {
128, (const float64_t *)twiddleCoefF64_128, armBitRevIndexTableF64_128, ARMBITREVINDEXTABLEF64_128_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_256) && defined(ARM_TABLE_BITREVIDX_FLT64_256))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len256 = {
256, (const float64_t *)twiddleCoefF64_256, armBitRevIndexTableF64_256, ARMBITREVINDEXTABLEF64_256_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_512) && defined(ARM_TABLE_BITREVIDX_FLT64_512))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len512 = {
512, (const float64_t *)twiddleCoefF64_512, armBitRevIndexTableF64_512, ARMBITREVINDEXTABLEF64_512_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_1024) && defined(ARM_TABLE_BITREVIDX_FLT64_1024))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len1024 = {
1024, (const float64_t *)twiddleCoefF64_1024, armBitRevIndexTableF64_1024, ARMBITREVINDEXTABLEF64_1024_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_2048) && defined(ARM_TABLE_BITREVIDX_FLT64_2048))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len2048 = {
2048, (const float64_t *)twiddleCoefF64_2048, armBitRevIndexTableF64_2048, ARMBITREVINDEXTABLEF64_2048_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_4096) && defined(ARM_TABLE_BITREVIDX_FLT64_4096))
const arm_cfft_instance_f64 arm_cfft_sR_f64_len4096 = {
4096, (const float64_t *)twiddleCoefF64_4096, armBitRevIndexTableF64_4096, ARMBITREVINDEXTABLEF64_4096_TABLE_LENGTH
};
#endif
/* Floating-point structs */
#if !defined(ARM_MATH_MVEF) || defined(ARM_MATH_AUTOVECTORIZE)
/*
Those structures cannot be used to initialize the MVE version of the FFT F32 instances.
So they are not compiled when MVE is defined.
For the MVE version, the new arm_cfft_init_f32 must be used.
*/
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_16) && defined(ARM_TABLE_BITREVIDX_FLT_16))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len16 = {
16, twiddleCoef_16, armBitRevIndexTable16, ARMBITREVINDEXTABLE_16_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_32) && defined(ARM_TABLE_BITREVIDX_FLT_32))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len32 = {
32, twiddleCoef_32, armBitRevIndexTable32, ARMBITREVINDEXTABLE_32_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_64) && defined(ARM_TABLE_BITREVIDX_FLT_64))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len64 = {
64, twiddleCoef_64, armBitRevIndexTable64, ARMBITREVINDEXTABLE_64_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_128) && defined(ARM_TABLE_BITREVIDX_FLT_128))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len128 = {
128, twiddleCoef_128, armBitRevIndexTable128, ARMBITREVINDEXTABLE_128_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_256) && defined(ARM_TABLE_BITREVIDX_FLT_256))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len256 = {
256, twiddleCoef_256, armBitRevIndexTable256, ARMBITREVINDEXTABLE_256_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_512) && defined(ARM_TABLE_BITREVIDX_FLT_512))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len512 = {
512, twiddleCoef_512, armBitRevIndexTable512, ARMBITREVINDEXTABLE_512_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_1024) && defined(ARM_TABLE_BITREVIDX_FLT_1024))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024 = {
1024, twiddleCoef_1024, armBitRevIndexTable1024, ARMBITREVINDEXTABLE_1024_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_2048) && defined(ARM_TABLE_BITREVIDX_FLT_2048))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048 = {
2048, twiddleCoef_2048, armBitRevIndexTable2048, ARMBITREVINDEXTABLE_2048_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_4096) && defined(ARM_TABLE_BITREVIDX_FLT_4096))
const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096 = {
4096, twiddleCoef_4096, armBitRevIndexTable4096, ARMBITREVINDEXTABLE_4096_TABLE_LENGTH
};
#endif
#endif /* !defined(ARM_MATH_MVEF) || defined(ARM_MATH_AUTOVECTORIZE) */
/* Fixed-point structs */
#if !defined(ARM_MATH_MVEI)
/*
Those structures cannot be used to initialize the MVE version of the FFT Q31 instances.
So they are not compiled when MVE is defined.
For the MVE version, the new arm_cfft_init_f32 must be used.
*/
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_16) && defined(ARM_TABLE_BITREVIDX_FXT_16))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len16 = {
16, twiddleCoef_16_q31, armBitRevIndexTable_fixed_16, ARMBITREVINDEXTABLE_FIXED_16_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_32) && defined(ARM_TABLE_BITREVIDX_FXT_32))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len32 = {
32, twiddleCoef_32_q31, armBitRevIndexTable_fixed_32, ARMBITREVINDEXTABLE_FIXED_32_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_64) && defined(ARM_TABLE_BITREVIDX_FXT_64))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len64 = {
64, twiddleCoef_64_q31, armBitRevIndexTable_fixed_64, ARMBITREVINDEXTABLE_FIXED_64_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_128) && defined(ARM_TABLE_BITREVIDX_FXT_128))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len128 = {
128, twiddleCoef_128_q31, armBitRevIndexTable_fixed_128, ARMBITREVINDEXTABLE_FIXED_128_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_256) && defined(ARM_TABLE_BITREVIDX_FXT_256))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len256 = {
256, twiddleCoef_256_q31, armBitRevIndexTable_fixed_256, ARMBITREVINDEXTABLE_FIXED_256_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_512) && defined(ARM_TABLE_BITREVIDX_FXT_512))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len512 = {
512, twiddleCoef_512_q31, armBitRevIndexTable_fixed_512, ARMBITREVINDEXTABLE_FIXED_512_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_1024) && defined(ARM_TABLE_BITREVIDX_FXT_1024))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024 = {
1024, twiddleCoef_1024_q31, armBitRevIndexTable_fixed_1024, ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_2048) && defined(ARM_TABLE_BITREVIDX_FXT_2048))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048 = {
2048, twiddleCoef_2048_q31, armBitRevIndexTable_fixed_2048, ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q31_4096) && defined(ARM_TABLE_BITREVIDX_FXT_4096))
const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096 = {
4096, twiddleCoef_4096_q31, armBitRevIndexTable_fixed_4096, ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_16) && defined(ARM_TABLE_BITREVIDX_FXT_16))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len16 = {
16, twiddleCoef_16_q15, armBitRevIndexTable_fixed_16, ARMBITREVINDEXTABLE_FIXED_16_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_32) && defined(ARM_TABLE_BITREVIDX_FXT_32))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len32 = {
32, twiddleCoef_32_q15, armBitRevIndexTable_fixed_32, ARMBITREVINDEXTABLE_FIXED_32_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_64) && defined(ARM_TABLE_BITREVIDX_FXT_64))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len64 = {
64, twiddleCoef_64_q15, armBitRevIndexTable_fixed_64, ARMBITREVINDEXTABLE_FIXED_64_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_128) && defined(ARM_TABLE_BITREVIDX_FXT_128))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len128 = {
128, twiddleCoef_128_q15, armBitRevIndexTable_fixed_128, ARMBITREVINDEXTABLE_FIXED_128_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_256) && defined(ARM_TABLE_BITREVIDX_FXT_256))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len256 = {
256, twiddleCoef_256_q15, armBitRevIndexTable_fixed_256, ARMBITREVINDEXTABLE_FIXED_256_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_512) && defined(ARM_TABLE_BITREVIDX_FXT_512))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len512 = {
512, twiddleCoef_512_q15, armBitRevIndexTable_fixed_512, ARMBITREVINDEXTABLE_FIXED_512_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_1024) && defined(ARM_TABLE_BITREVIDX_FXT_1024))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024 = {
1024, twiddleCoef_1024_q15, armBitRevIndexTable_fixed_1024, ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_2048) && defined(ARM_TABLE_BITREVIDX_FXT_2048))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048 = {
2048, twiddleCoef_2048_q15, armBitRevIndexTable_fixed_2048, ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_4096) && defined(ARM_TABLE_BITREVIDX_FXT_4096))
const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096 = {
4096, twiddleCoef_4096_q15, armBitRevIndexTable_fixed_4096, ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH
};
#endif
#endif /* !defined(ARM_MATH_MVEI) */
/* Structure for real-value inputs */
/* Double precision strucs */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_32) && defined(ARM_TABLE_BITREVIDX_FLT64_32) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_32))
const arm_rfft_fast_instance_f64 arm_rfft_fast_sR_f64_len32 = {
{ 16, (const float64_t *)twiddleCoefF64_16, armBitRevIndexTableF64_16, ARMBITREVINDEXTABLEF64_16_TABLE_LENGTH },
32U,
(float64_t *)twiddleCoefF64_rfft_32
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_64) && defined(ARM_TABLE_BITREVIDX_FLT64_64) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_64))
const arm_rfft_fast_instance_f64 arm_rfft_fast_sR_f64_len64 = {
{ 32, (const float64_t *)twiddleCoefF64_32, armBitRevIndexTableF64_32, ARMBITREVINDEXTABLEF64_32_TABLE_LENGTH },
64U,
(float64_t *)twiddleCoefF64_rfft_64
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_128) && defined(ARM_TABLE_BITREVIDX_FLT64_128) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_128))
const arm_rfft_fast_instance_f64 arm_rfft_fast_sR_f64_len128 = {
{ 64, (const float64_t *)twiddleCoefF64_64, armBitRevIndexTableF64_64, ARMBITREVINDEXTABLEF64_64_TABLE_LENGTH },
128U,
(float64_t *)twiddleCoefF64_rfft_128
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_256) && defined(ARM_TABLE_BITREVIDX_FLT64_256) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_256))
const arm_rfft_fast_instance_f64 arm_rfft_fast_sR_f64_len256 = {
{ 128, (const float64_t *)twiddleCoefF64_128, armBitRevIndexTableF64_128, ARMBITREVINDEXTABLEF64_128_TABLE_LENGTH },
256U,
(float64_t *)twiddleCoefF64_rfft_256
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_512) && defined(ARM_TABLE_BITREVIDX_FLT64_512) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_512))
const arm_rfft_fast_instance_f64 arm_rfft_fast_sR_f64_len512 = {
{ 256, (const float64_t *)twiddleCoefF64_256, armBitRevIndexTableF64_256, ARMBITREVINDEXTABLEF64_256_TABLE_LENGTH },
512U,
(float64_t *)twiddleCoefF64_rfft_512
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_1024) && defined(ARM_TABLE_BITREVIDX_FLT64_1024) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_1024))
const arm_rfft_fast_instance_f64 arm_rfft_fast_sR_f64_len1024 = {
{ 512, (const float64_t *)twiddleCoefF64_512, armBitRevIndexTableF64_512, ARMBITREVINDEXTABLEF64_512_TABLE_LENGTH },
1024U,
(float64_t *)twiddleCoefF64_rfft_1024
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_2048) && defined(ARM_TABLE_BITREVIDX_FLT64_2048) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_2048))
const arm_rfft_fast_instance_f64 arm_rfft_fast_sR_f64_len2048 = {
{ 1024, (const float64_t *)twiddleCoefF64_1024, armBitRevIndexTableF64_1024, ARMBITREVINDEXTABLEF64_1024_TABLE_LENGTH },
2048U,
(float64_t *)twiddleCoefF64_rfft_2048
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F64_4096) && defined(ARM_TABLE_BITREVIDX_FLT64_4096) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F64_4096))
const arm_rfft_fast_instance_f64 arm_rfft_fast_sR_f64_len4096 = {
{ 2048, (const float64_t *)twiddleCoefF64_2048, armBitRevIndexTableF64_2048, ARMBITREVINDEXTABLEF64_2048_TABLE_LENGTH },
4096U,
(float64_t *)twiddleCoefF64_rfft_4096
};
#endif
/* Floating-point structs */
#if !defined(ARM_MATH_MVEF) || defined(ARM_MATH_AUTOVECTORIZE)
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_32) && defined(ARM_TABLE_BITREVIDX_FLT_32) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_32))
const arm_rfft_fast_instance_f32 arm_rfft_fast_sR_f32_len32 = {
{ 16, twiddleCoef_16, armBitRevIndexTable16, ARMBITREVINDEXTABLE_16_TABLE_LENGTH },
32U,
(float32_t *)twiddleCoef_rfft_32
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_64) && defined(ARM_TABLE_BITREVIDX_FLT_64) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_64))
const arm_rfft_fast_instance_f32 arm_rfft_fast_sR_f32_len64 = {
{ 32, twiddleCoef_32, armBitRevIndexTable32, ARMBITREVINDEXTABLE_32_TABLE_LENGTH },
64U,
(float32_t *)twiddleCoef_rfft_64
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_128) && defined(ARM_TABLE_BITREVIDX_FLT_128) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_128))
const arm_rfft_fast_instance_f32 arm_rfft_fast_sR_f32_len128 = {
{ 64, twiddleCoef_64, armBitRevIndexTable64, ARMBITREVINDEXTABLE_64_TABLE_LENGTH },
128U,
(float32_t *)twiddleCoef_rfft_128
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_256) && defined(ARM_TABLE_BITREVIDX_FLT_256) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_256))
const arm_rfft_fast_instance_f32 arm_rfft_fast_sR_f32_len256 = {
{ 128, twiddleCoef_128, armBitRevIndexTable128, ARMBITREVINDEXTABLE_128_TABLE_LENGTH },
256U,
(float32_t *)twiddleCoef_rfft_256
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_512) && defined(ARM_TABLE_BITREVIDX_FLT_512) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_512))
const arm_rfft_fast_instance_f32 arm_rfft_fast_sR_f32_len512 = {
{ 256, twiddleCoef_256, armBitRevIndexTable256, ARMBITREVINDEXTABLE_256_TABLE_LENGTH },
512U,
(float32_t *)twiddleCoef_rfft_512
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_1024) && defined(ARM_TABLE_BITREVIDX_FLT_1024) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_1024))
const arm_rfft_fast_instance_f32 arm_rfft_fast_sR_f32_len1024 = {
{ 512, twiddleCoef_512, armBitRevIndexTable512, ARMBITREVINDEXTABLE_512_TABLE_LENGTH },
1024U,
(float32_t *)twiddleCoef_rfft_1024
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_2048) && defined(ARM_TABLE_BITREVIDX_FLT_2048) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_2048))
const arm_rfft_fast_instance_f32 arm_rfft_fast_sR_f32_len2048 = {
{ 1024, twiddleCoef_1024, armBitRevIndexTable1024, ARMBITREVINDEXTABLE_1024_TABLE_LENGTH },
2048U,
(float32_t *)twiddleCoef_rfft_2048
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_F32_4096) && defined(ARM_TABLE_BITREVIDX_FLT_4096) && defined(ARM_TABLE_TWIDDLECOEF_RFFT_F32_4096))
const arm_rfft_fast_instance_f32 arm_rfft_fast_sR_f32_len4096 = {
{ 2048, twiddleCoef_2048, armBitRevIndexTable2048, ARMBITREVINDEXTABLE_2048_TABLE_LENGTH },
4096U,
(float32_t *)twiddleCoef_rfft_4096
};
#endif
#endif /* #if !defined(ARM_MATH_MVEF) || defined(ARM_MATH_AUTOVECTORIZE) */
/* Fixed-point structs */
/* q31_t */
#if !defined(ARM_MATH_MVEI)
/*
Those structures cannot be used to initialize the MVE version of the FFT Q31 instances.
So they are not compiled when MVE is defined.
For the MVE version, the new arm_cfft_init_f32 must be used.
*/
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_16) && defined(ARM_TABLE_BITREVIDX_FXT_16))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len32 = {
32U,
0,
1,
256U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len16
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_32) && defined(ARM_TABLE_BITREVIDX_FXT_32))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len64 = {
64U,
0,
1,
128U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len32
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_64) && defined(ARM_TABLE_BITREVIDX_FXT_64))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len128 = {
128U,
0,
1,
64U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len64
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_128) && defined(ARM_TABLE_BITREVIDX_FXT_128))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len256 = {
256U,
0,
1,
32U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len128
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_256) && defined(ARM_TABLE_BITREVIDX_FXT_256))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len512 = {
512U,
0,
1,
16U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len256
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_512) && defined(ARM_TABLE_BITREVIDX_FXT_512))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len1024 = {
1024U,
0,
1,
8U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len512
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_1024) && defined(ARM_TABLE_BITREVIDX_FXT_1024))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len2048 = {
2048U,
0,
1,
4U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len1024
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_2048) && defined(ARM_TABLE_BITREVIDX_FXT_2048))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len4096 = {
4096U,
0,
1,
2U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len2048
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q31) && defined(ARM_TABLE_TWIDDLECOEF_Q31_4096) && defined(ARM_TABLE_BITREVIDX_FXT_4096))
const arm_rfft_instance_q31 arm_rfft_sR_q31_len8192 = {
8192U,
0,
1,
1U,
(q31_t*)realCoefAQ31,
(q31_t*)realCoefBQ31,
&arm_cfft_sR_q31_len4096
};
#endif
/* q15_t */
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_16) && defined(ARM_TABLE_BITREVIDX_FXT_16))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len32 = {
32U,
0,
1,
256U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len16
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_32) && defined(ARM_TABLE_BITREVIDX_FXT_32))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len64 = {
64U,
0,
1,
128U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len32
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_64) && defined(ARM_TABLE_BITREVIDX_FXT_64))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len128 = {
128U,
0,
1,
64U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len64
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_128) && defined(ARM_TABLE_BITREVIDX_FXT_128))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len256 = {
256U,
0,
1,
32U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len128
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_256) && defined(ARM_TABLE_BITREVIDX_FXT_256))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len512 = {
512U,
0,
1,
16U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len256
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_512) && defined(ARM_TABLE_BITREVIDX_FXT_512))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len1024 = {
1024U,
0,
1,
8U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len512
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_1024) && defined(ARM_TABLE_BITREVIDX_FXT_1024))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len2048 = {
2048U,
0,
1,
4U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len1024
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_2048) && defined(ARM_TABLE_BITREVIDX_FXT_2048))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len4096 = {
4096U,
0,
1,
2U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len2048
};
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_REALCOEF_Q15) && defined(ARM_TABLE_TWIDDLECOEF_Q15_4096) && defined(ARM_TABLE_BITREVIDX_FXT_4096))
const arm_rfft_instance_q15 arm_rfft_sR_q15_len8192 = {
8192U,
0,
1,
1U,
(q15_t*)realCoefAQ15,
(q15_t*)realCoefBQ15,
&arm_cfft_sR_q15_len4096
};
#endif
#endif /* !defined(ARM_MATH_MVEI) */
#endif
@@ -1,308 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_float_to_q15.c
* Description: Converts the elements of the floating-point vector to Q15 vector
*
* $Date: 18. March 2019
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-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 "arm_math.h"
/**
@ingroup groupSupport
*/
/**
@addtogroup float_to_x
@{
*/
/**
@brief Converts the elements of the floating-point vector to Q15 vector.
@param[in] pSrc points to the floating-point input vector
@param[out] pDst points to the Q15 output vector
@param[in] blockSize number of samples in each vector
@return none
@par Details
The equation used for the conversion process is:
<pre>
pDst[n] = (q15_t)(pSrc[n] * 32768); 0 <= n < blockSize.
</pre>
@par Scaling and Overflow Behavior
The function uses saturating arithmetic.
Results outside of the allowable Q15 range [0x8000 0x7FFF] are saturated.
@note
In order to apply rounding, the library should be rebuilt with the ROUNDING macro
defined in the preprocessor section of project options.
*/
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
void arm_float_to_q15(
const float32_t * pSrc,
q15_t * pDst,
uint32_t blockSize)
{
uint32_t blkCnt;
float32_t maxQ = (float32_t) Q15_MAX;
f32x4x2_t tmp;
q15x8_t vecDst;
#ifdef ARM_MATH_ROUNDING
float32_t in;
#endif
blkCnt = blockSize >> 3;
while (blkCnt > 0U)
{
/* C = A * 32768 */
/* convert from float to q15 and then store the results in the destination buffer */
tmp = vld2q(pSrc);
tmp.val[0] = vmulq(tmp.val[0], maxQ);
tmp.val[1] = vmulq(tmp.val[1], maxQ);
vecDst = vqmovnbq(vecDst, vcvtaq_s32_f32(tmp.val[0]));
vecDst = vqmovntq(vecDst, vcvtaq_s32_f32(tmp.val[1]));
vst1q(pDst, vecDst);
/*
* Decrement the blockSize loop counter
*/
blkCnt--;
pDst += 8;
pSrc += 8;
}
blkCnt = blockSize & 7;
while (blkCnt > 0U)
{
/* C = A * 32768 */
/* convert from float to Q15 and store result in destination buffer */
#ifdef ARM_MATH_ROUNDING
in = (*pSrc++ * 32768.0f);
in += in > 0.0f ? 0.5f : -0.5f;
*pDst++ = (q15_t) (__SSAT((q31_t) (in), 16));
#else
/* C = A * 32768 */
/* Convert from float to q15 and then store the results in the destination buffer */
*pDst++ = (q15_t) __SSAT((q31_t) (*pSrc++ * 32768.0f), 16);
#endif /* #ifdef ARM_MATH_ROUNDING */
/* Decrement loop counter */
blkCnt--;
}
}
#else
#if defined(ARM_MATH_NEON_EXPERIMENTAL)
void arm_float_to_q15(
const float32_t * pSrc,
q15_t * pDst,
uint32_t blockSize)
{
const float32_t *pIn = pSrc; /* Src pointer */
uint32_t blkCnt; /* loop counter */
float32x4_t inV;
#ifdef ARM_MATH_ROUNDING
float32x4_t zeroV = vdupq_n_f32(0.0f);
float32x4_t pHalf = vdupq_n_f32(0.5f / 32768.0f);
float32x4_t mHalf = vdupq_n_f32(-0.5f / 32768.0f);
float32x4_t r;
uint32x4_t cmp;
float32_t in;
#endif
int32x4_t cvt;
int16x4_t outV;
blkCnt = blockSize >> 2U;
/* Compute 4 outputs at a time.
** a second loop below computes the remaining 1 to 3 samples. */
while (blkCnt > 0U)
{
#ifdef ARM_MATH_ROUNDING
/* C = A * 32768 */
/* Convert from float to q15 and then store the results in the destination buffer */
inV = vld1q_f32(pIn);
cmp = vcgtq_f32(inV,zeroV);
r = vbslq_f32(cmp,pHalf,mHalf);
inV = vaddq_f32(inV, r);
pIn += 4;
cvt = vcvtq_n_s32_f32(inV,15);
outV = vqmovn_s32(cvt);
vst1_s16(pDst, outV);
pDst += 4;
#else
/* C = A * 32768 */
/* Convert from float to q15 and then store the results in the destination buffer */
inV = vld1q_f32(pIn);
cvt = vcvtq_n_s32_f32(inV,15);
outV = vqmovn_s32(cvt);
vst1_s16(pDst, outV);
pDst += 4;
pIn += 4;
#endif /* #ifdef ARM_MATH_ROUNDING */
/* Decrement the loop counter */
blkCnt--;
}
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
** No loop unrolling is used. */
blkCnt = blockSize & 3;
while (blkCnt > 0U)
{
#ifdef ARM_MATH_ROUNDING
/* C = A * 32768 */
/* Convert from float to q15 and then store the results in the destination buffer */
in = *pIn++;
in = (in * 32768.0f);
in += in > 0.0f ? 0.5f : -0.5f;
*pDst++ = (q15_t) (__SSAT((q31_t) (in), 16));
#else
/* C = A * 32768 */
/* Convert from float to q15 and then store the results in the destination buffer */
*pDst++ = (q15_t) __SSAT((q31_t) (*pIn++ * 32768.0f), 16);
#endif /* #ifdef ARM_MATH_ROUNDING */
/* Decrement the loop counter */
blkCnt--;
}
}
#else
void arm_float_to_q15(
const float32_t * pSrc,
q15_t * pDst,
uint32_t blockSize)
{
uint32_t blkCnt; /* Loop counter */
const float32_t *pIn = pSrc; /* Source pointer */
#ifdef ARM_MATH_ROUNDING
float32_t in;
#endif /* #ifdef ARM_MATH_ROUNDING */
#if defined (ARM_MATH_LOOPUNROLL)
/* Loop unrolling: Compute 4 outputs at a time */
blkCnt = blockSize >> 2U;
while (blkCnt > 0U)
{
/* C = A * 32768 */
/* convert from float to Q15 and store result in destination buffer */
#ifdef ARM_MATH_ROUNDING
in = (*pIn++ * 32768.0f);
in += in > 0.0f ? 0.5f : -0.5f;
*pDst++ = (q15_t) (__SSAT((q31_t) (in), 16));
in = (*pIn++ * 32768.0f);
in += in > 0.0f ? 0.5f : -0.5f;
*pDst++ = (q15_t) (__SSAT((q31_t) (in), 16));
in = (*pIn++ * 32768.0f);
in += in > 0.0f ? 0.5f : -0.5f;
*pDst++ = (q15_t) (__SSAT((q31_t) (in), 16));
in = (*pIn++ * 32768.0f);
in += in > 0.0f ? 0.5f : -0.5f;
*pDst++ = (q15_t) (__SSAT((q31_t) (in), 16));
#else
*pDst++ = (q15_t) __SSAT((q31_t) (*pIn++ * 32768.0f), 16);
*pDst++ = (q15_t) __SSAT((q31_t) (*pIn++ * 32768.0f), 16);
*pDst++ = (q15_t) __SSAT((q31_t) (*pIn++ * 32768.0f), 16);
*pDst++ = (q15_t) __SSAT((q31_t) (*pIn++ * 32768.0f), 16);
#endif /* #ifdef ARM_MATH_ROUNDING */
/* Decrement loop counter */
blkCnt--;
}
/* Loop unrolling: Compute remaining outputs */
blkCnt = blockSize % 0x4U;
#else
/* Initialize blkCnt with number of samples */
blkCnt = blockSize;
#endif /* #if defined (ARM_MATH_LOOPUNROLL) */
while (blkCnt > 0U)
{
/* C = A * 32768 */
/* convert from float to Q15 and store result in destination buffer */
#ifdef ARM_MATH_ROUNDING
in = (*pIn++ * 32768.0f);
in += in > 0.0f ? 0.5f : -0.5f;
*pDst++ = (q15_t) (__SSAT((q31_t) (in), 16));
#else
/* C = A * 32768 */
/* Convert from float to q15 and then store the results in the destination buffer */
*pDst++ = (q15_t) __SSAT((q31_t) (*pIn++ * 32768.0f), 16);
#endif /* #ifdef ARM_MATH_ROUNDING */
/* Decrement loop counter */
blkCnt--;
}
}
#endif /* #if defined(ARM_MATH_NEON) */
#endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
/**
@} end of float_to_x group
*/
@@ -1,134 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_bitreversal2.c
* Description: Bitreversal functions
*
* $Date: 18. March 2019
* $Revision: V1.0.0
*
* Target Processor: Cortex-M 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 "arm_math.h"
#include "arm_common_tables.h"
/**
@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
@return none
*/
void arm_bitreversal_64(
uint64_t *pSrc,
const uint16_t bitRevLen,
const uint16_t *pBitRevTab)
{
uint64_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;
}
}
/**
@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
@return none
*/
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;
}
}
/**
@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
@return none
*/
void arm_bitreversal_16(
uint16_t *pSrc,
const uint16_t bitRevLen,
const uint16_t *pBitRevTab)
{
uint16_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;
}
}
@@ -1,949 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_cfft_q15.c
* Description: Combined Radix Decimation in Q15 Frequency CFFT processing function
*
* $Date: 18. March 2019
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-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 "arm_math.h"
#if defined(ARM_MATH_MVEI)
#include "arm_vec_fft.h"
static void arm_bitreversal_16_inpl_mve(
uint16_t *pSrc,
const uint16_t bitRevLen,
const uint16_t *pBitRevTab)
{
uint32_t *src = (uint32_t *)pSrc;
uint32_t blkCnt; /* loop counters */
uint32x4_t bitRevTabOff;
uint16x8_t one = vdupq_n_u16(1);
blkCnt = (bitRevLen / 2) / 4;
while (blkCnt > 0U) {
bitRevTabOff = vldrhq_u16(pBitRevTab);
pBitRevTab += 8;
uint32x4_t bitRevOff1 = vmullbq_int_u16(bitRevTabOff, one);
uint32x4_t bitRevOff2 = vmulltq_int_u16(bitRevTabOff, one);
bitRevOff1 = bitRevOff1 >> 3;
bitRevOff2 = bitRevOff2 >> 3;
uint32x4_t in1 = vldrwq_gather_shifted_offset_u32(src, bitRevOff1);
uint32x4_t in2 = vldrwq_gather_shifted_offset_u32(src, bitRevOff2);
vstrwq_scatter_shifted_offset_u32(src, bitRevOff1, in2);
vstrwq_scatter_shifted_offset_u32(src, bitRevOff2, in1);
/*
* Decrement the blockSize loop counter
*/
blkCnt--;
}
/*
* tail
* (will be merged thru tail predication)
*/
blkCnt = bitRevLen & 7;
if (blkCnt > 0U) {
mve_pred16_t p0 = vctp16q(blkCnt);
bitRevTabOff = vldrhq_z_u16(pBitRevTab, p0);
uint32x4_t bitRevOff1 = vmullbq_int_u16(bitRevTabOff, one);
uint32x4_t bitRevOff2 = vmulltq_int_u16(bitRevTabOff, one);
bitRevOff1 = bitRevOff1 >> 3;
bitRevOff2 = bitRevOff2 >> 3;
uint32x4_t in1 = vldrwq_gather_shifted_offset_z_u32(src, bitRevOff1, p0);
uint32x4_t in2 = vldrwq_gather_shifted_offset_z_u32(src, bitRevOff2, p0);
vstrwq_scatter_shifted_offset_p_u32(src, bitRevOff1, in2, p0);
vstrwq_scatter_shifted_offset_p_u32(src, bitRevOff2, in1, p0);
}
}
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;
q15x8_t vecW;
uint32_t blkCnt;
uint32_t n1, n2;
uint32_t stage = 0;
int32_t iter = 1;
static const uint32_t strides[4] = {
(0 - 16) * sizeof(q15_t *), (4 - 16) * sizeof(q15_t *),
(8 - 16) * sizeof(q15_t *), (12 - 16) * 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)
{
for (int i = 0; i < iter; i++)
{
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 const *pW1, *pW2, *pW3;
q15_t *inA = pSrc + CMPLX_DIM * i * n1;
q15_t *inB = inA + n2 * CMPLX_DIM;
q15_t *inC = inB + n2 * CMPLX_DIM;
q15_t *inD = inC + n2 * CMPLX_DIM;
pW1 = p_rearranged_twiddle_tab_stride1;
pW2 = p_rearranged_twiddle_tab_stride2;
pW3 = p_rearranged_twiddle_tab_stride3;
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);
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);
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);
vst1q(inD, vecTmp1);
inD += 8;
vecA = vldrhq_s16(inA);
vecC = vldrhq_s16(inC);
blkCnt--;
}
}
n1 = n2;
n2 >>= 2u;
iter = iter << 2;
stage++;
}
/*
* start of Last stage process
*/
uint32x4_t vecScGathAddr = *(uint32x4_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, (q15x8_t) vecTmp0);
vecTmp0 = vhsubq(vecSum0, vecSum1);
vstrwq_scatter_base_s32(vecScGathAddr, -64 + 4, (q15x8_t) vecTmp0);
vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1);
vstrwq_scatter_base_s32(vecScGathAddr, -64 + 8, (q15x8_t) vecTmp0);
vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1);
vstrwq_scatter_base_s32(vecScGathAddr, -64 + 12, (q15x8_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);
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;
q15x8_t vecW;
uint32_t blkCnt;
uint32_t n1, n2;
uint32_t stage = 0;
int32_t iter = 1;
static const uint32_t strides[4] = {
(0 - 16) * sizeof(q15_t *), (4 - 16) * sizeof(q15_t *),
(8 - 16) * sizeof(q15_t *), (12 - 16) * 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)
{
for (int i = 0; i < iter; i++)
{
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 const *pW1, *pW2, *pW3;
q15_t *inA = pSrc + CMPLX_DIM * i * n1;
q15_t *inB = inA + n2 * CMPLX_DIM;
q15_t *inC = inB + n2 * CMPLX_DIM;
q15_t *inD = inC + n2 * CMPLX_DIM;
pW1 = p_rearranged_twiddle_tab_stride1;
pW2 = p_rearranged_twiddle_tab_stride2;
pW3 = p_rearranged_twiddle_tab_stride3;
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);
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);
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);
vst1q(inD, vecTmp1);
inD += 8;
vecA = vldrhq_s16(inA);
vecC = vldrhq_s16(inC);
blkCnt--;
}
}
n1 = n2;
n2 >>= 2u;
iter = iter << 2;
stage++;
}
/*
* start of Last stage process
*/
uint32x4_t vecScGathAddr = *(uint32x4_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, (q15x8_t) vecTmp0);
vecTmp0 = vhsubq(vecSum0, vecSum1);
vstrwq_scatter_base_s32(vecScGathAddr, -64 + 4, (q15x8_t) vecTmp0);
vecTmp0 = MVE_CMPLX_ADD_FX_A_ixB(vecDiff0, vecDiff1);
vstrwq_scatter_base_s32(vecScGathAddr, -64 + 8, (q15x8_t) vecTmp0);
vecTmp0 = MVE_CMPLX_SUB_FX_A_ixB(vecDiff0, vecDiff1);
vstrwq_scatter_base_s32(vecScGathAddr, -64 + 12, (q15x8_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);
}
}
/**
@ingroup groupTransforms
*/
/**
@addtogroup ComplexFFT
@{
*/
/**
@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 of size <code>2*fftLen</code>. 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
@return none
*/
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
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);
void arm_cfft_radix4by2_q15(
q15_t * pSrc,
uint32_t fftLen,
const q15_t * pCoef);
void arm_cfft_radix4by2_inverse_q15(
q15_t * pSrc,
uint32_t fftLen,
const q15_t * pCoef);
/**
@ingroup groupTransforms
*/
/**
@addtogroup ComplexFFT
@{
*/
/**
@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 of size <code>2*fftLen</code>. 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
@return none
*/
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);
}
/**
@} end of ComplexFFT group
*/
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 ((q15_t **) &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) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF));
}
#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;
}
}
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 ((q15_t **) &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) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF));
}
#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(ARM_MATH_MVEI) */
@@ -1,239 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_rfft_init_q15.c
* Description: RFFT & RIFFT Q15 initialisation function
*
* $Date: 18. March 2019
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-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 "arm_math.h"
#include "arm_common_tables.h"
#include "arm_const_structs.h"
/**
@addtogroup RealFFT
@{
*/
/**
@brief 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.
*/
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_SUCCESS;
/* Initialize the Real FFT length */
S->fftLenReal = (uint16_t) fftLenReal;
/* 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;
/* Initialization of coef modifier depending on the FFT length */
switch (S->fftLenReal)
{
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_4096) && defined(ARM_TABLE_BITREVIDX_FXT_4096))
case 8192U:
S->twidCoefRModifier = 1U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),4096);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len4096;
#endif
break;
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_2048) && defined(ARM_TABLE_BITREVIDX_FXT_2048))
case 4096U:
S->twidCoefRModifier = 2U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),2048);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len2048;
#endif
break;
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_1024) && defined(ARM_TABLE_BITREVIDX_FXT_1024))
case 2048U:
S->twidCoefRModifier = 4U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),1024);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len1024;
#endif
break;
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_512) && defined(ARM_TABLE_BITREVIDX_FXT_512))
case 1024U:
S->twidCoefRModifier = 8U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),512);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len512;
#endif
break;
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_256) && defined(ARM_TABLE_BITREVIDX_FXT_256))
case 512U:
S->twidCoefRModifier = 16U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),256);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len256;
#endif
break;
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_128) && defined(ARM_TABLE_BITREVIDX_FXT_128))
case 256U:
S->twidCoefRModifier = 32U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),128);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len128;
#endif
break;
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_64) && defined(ARM_TABLE_BITREVIDX_FXT_64))
case 128U:
S->twidCoefRModifier = 64U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),64);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len64;
#endif
break;
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_32) && defined(ARM_TABLE_BITREVIDX_FXT_32))
case 64U:
S->twidCoefRModifier = 128U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),32);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len32;
#endif
break;
#endif
#if !defined(ARM_DSP_CONFIG_TABLES) || defined(ARM_ALL_FFT_TABLES) || (defined(ARM_TABLE_TWIDDLECOEF_Q15_16) && defined(ARM_TABLE_BITREVIDX_FXT_16))
case 32U:
S->twidCoefRModifier = 256U;
#if defined(ARM_MATH_MVEI)
status=arm_cfft_init_q15(&(S->cfftInst),16);
if (status != ARM_MATH_SUCCESS)
{
return(status);
}
#else
S->pCfft = &arm_cfft_sR_q15_len16;
#endif
break;
#endif
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);
}
/**
@} end of RealFFT group
*/
@@ -1,592 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_rfft_q15.c
* Description: RFFT & RIFFT Q15 process function
*
* $Date: 18. March 2019
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-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 "arm_math.h"
/* ----------------------------------------------------------------------
* Internal functions prototypes
* -------------------------------------------------------------------- */
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);
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);
/**
@addtogroup RealFFT
@{
*/
/**
@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
@return none
@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
\image html RFFTQ15.gif "Input and Output Formats for Q15 RFFT"
@par
\image html RIFFTQ15.gif "Input and Output Formats for Q15 RIFFT"
@par
If the input buffer is of length N, the output buffer must have length 2*N.
The input buffer is modified by this function.
*/
void arm_rfft_q15(
const arm_rfft_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst)
{
#if defined(ARM_MATH_MVEI)
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;
uint32_t i;
/* 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);
for(i = 0; i < S->fftLenReal; i++)
{
pDst[i] = pDst[i] << 1U;
}
}
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);
}
}
/**
@} end of RealFFT 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
@return none
@par
The function implements a Real FFT
*/
#if defined(ARM_MATH_MVEI)
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)
{
q15_t const *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
q15_t *pDst1 = &pDst[2], *pDst2 = &pDst[(4U * fftLen) - 1U - 14]; /* temp pointers for output buffer */
q15_t const *pSrc1 = &pSrc[2], *pSrc2 = &pSrc[(2U * fftLen) - 1U - 14]; /* temp pointers for input buffer */
q15_t const *pVecSrc1;
q15_t *pVecDst1;
q15x8x2_t vecIn, vecSum;
uint32_t blkCnt;
uint16x8_t vecStridesFwd, vecStridesBkwd;
q15x8_t vecInBkwd, vecCoefFwd0, vecCoefFwd1;
/*
* Init coefficient pointers
*/
pCoefA = &pATable[modifier * 2U];
pCoefB = &pBTable[modifier * 2U];
/*
* scatter / gather offsets
* for ascending & descending addressing
*/
vecStridesFwd = vidupq_u16((uint32_t)0, 2); // 0, 2, 4, 6, 8, 10, 12, 14
vecStridesBkwd = vddupq_u16(14, 2); // 14, 12, 10, 8, 6, 4, 2, 0
vecStridesFwd = vecStridesFwd * (uint16_t) modifier;
pVecSrc1 = (q15_t const *) pSrc1;
pVecDst1 = pDst1;
blkCnt = fftLen >> 3;
while (blkCnt > 0U)
{
vecCoefFwd0 = vldrhq_gather_shifted_offset(pCoefA, vecStridesFwd);
vecCoefFwd1 = vldrhq_gather_shifted_offset(&pCoefA[1], vecStridesFwd);
vecIn = vld2q(pVecSrc1);
pVecSrc1 += 16;
/*
* outR = *pSrc1 * CoefA1;
*/
vecSum.val[0] = vrmulhq(vecIn.val[0], vecCoefFwd0);
/*
* outI = *pSrc1++ * CoefA2;
*/
vecSum.val[1] = vrmulhq(vecIn.val[0], vecCoefFwd1);
vecInBkwd = vldrhq_gather_shifted_offset(pSrc2, vecStridesBkwd);
/*
* outR -= (*pSrc1 + *pSrc2) * CoefA2;
*/
vecInBkwd = vqaddq(vecIn.val[1], vecInBkwd);
vecSum.val[0] = vqsubq(vecSum.val[0], vrmulhq(vecInBkwd, vecCoefFwd1));
vecInBkwd = vldrhq_gather_shifted_offset(pSrc2, vecStridesBkwd);
/*
* outI += *pSrc1++ * CoefA1;
*/
vecSum.val[1] = vqaddq(vecSum.val[1], vrmulhq(vecIn.val[1], vecCoefFwd0));
vecCoefFwd0 = vldrhq_gather_shifted_offset(pCoefB, vecStridesFwd);
/*
* outI -= *pSrc2-- * CoefB1;
*/
vecSum.val[1] = vqsubq(vecSum.val[1], vrmulhq(vecInBkwd, vecCoefFwd0));
vecInBkwd = vldrhq_gather_shifted_offset(&pSrc2[-1], vecStridesBkwd);
/*
* outI -= *pSrc2 * CoefA2;
*/
vecSum.val[1] = vqsubq(vecSum.val[1], vrmulhq(vecInBkwd, vecCoefFwd1));
/*
* outR += *pSrc2-- * CoefB1;
*/
vecSum.val[0] = vqaddq(vecSum.val[0], vrmulhq(vecInBkwd, vecCoefFwd0));
vst2q(pVecDst1, vecSum);
pVecDst1 += 16;
/*
* write complex conjugate output
*/
vecSum.val[1] = -vecSum.val[1];
vstrhq_scatter_shifted_offset(pDst2, vecStridesBkwd, vecSum.val[1]);
vstrhq_scatter_shifted_offset(&pDst2[-1], vecStridesBkwd, vecSum.val[0]);
/*
* update fwd and backwd offsets
*/
vecStridesFwd = vecStridesFwd + (uint16_t)(modifier * 16U);
/* cannot use negative 16-bit offsets (would lead to positive 32-65K jump*/
//vecStridesBkwd = vecStridesBkwd - (uint16_t)16;
pSrc2 = pSrc2 - 16;
pDst2 = pDst2 - 16;
blkCnt--;
}
pDst[2U * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
pDst[(2U * fftLen) + 1U] = 0;
pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
pDst[1] = 0;
}
#else
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
@return none
@par
The function implements a Real IFFT
*/
#if defined(ARM_MATH_MVEI)
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)
{
q15_t const *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
q15_t const *pSrc1 = &pSrc[0], *pSrc2 = &pSrc[(2U * fftLen) + 1U - 14U];
q15_t *pDst1 = &pDst[0];
q15_t const *pVecSrc1;
q15_t *pVecDst1;
q15x8x2_t vecIn, vecSum;
uint32_t blkCnt;
uint16x8_t vecStridesFwd, vecStridesBkwd;
q15x8_t vecInBkwd, vecCoefFwd0, vecCoefFwd1;
/*
* Init coefficient pointers
*/
pCoefA = &pATable[0];
pCoefB = &pBTable[0];
/*
* scatter / gather offsets
* for ascending & descending addressing
*/
vecStridesFwd = vidupq_u16((uint32_t)0, 2); // 0, 2, 4, 6, 8, 10, 12, 14
vecStridesBkwd = vddupq_u16(14, 2); // 14, 12, 10, 8, 6, 4, 2, 0
vecStridesFwd = vecStridesFwd * (uint16_t) modifier;
pVecSrc1 = (q15_t const *) pSrc1;
pVecDst1 = pDst1;
blkCnt = fftLen >> 3;
while (blkCnt > 0U)
{
vecCoefFwd0 = vldrhq_gather_shifted_offset(pCoefA, vecStridesFwd);
vecCoefFwd1 = vldrhq_gather_shifted_offset(&pCoefA[1], vecStridesFwd);
vecIn = vld2q(pVecSrc1);
pVecSrc1 += 16;
/*
* outR = *pSrc1 * CoefA1;
*/
vecSum.val[0] = vmulhq(vecIn.val[0], vecCoefFwd0);
/*
* outI = -(*pSrc1++) * CoefA2;
*/
vecIn.val[0] = vnegq(vecIn.val[0]);
vecSum.val[1] = vmulhq(vecIn.val[0], vecCoefFwd1);
vecInBkwd = vldrhq_gather_shifted_offset(pSrc2, vecStridesBkwd);
/*
* outR += (*pSrc1 + *pSrc2) * CoefA2;
*/
vecInBkwd = vqaddq(vecIn.val[1], vecInBkwd);
vecSum.val[0] = vqaddq(vecSum.val[0], vmulhq(vecInBkwd, vecCoefFwd1));
vecInBkwd = vldrhq_gather_shifted_offset(pSrc2, vecStridesBkwd);
/*
* outI += *pSrc1++ * CoefA1;
*/
vecSum.val[1] = vqaddq(vecSum.val[1], vmulhq(vecIn.val[1], vecCoefFwd0));
vecCoefFwd0 = vldrhq_gather_shifted_offset(pCoefB, vecStridesFwd);
/*
* outI -= *pSrc2-- * CoefB1;
*/
vecSum.val[1] = vqsubq(vecSum.val[1], vmulhq(vecInBkwd, vecCoefFwd0));
vecInBkwd = vldrhq_gather_shifted_offset(&pSrc2[-1], vecStridesBkwd);
/*
* outI += *pSrc2 * CoefA2;
*/
vecSum.val[1] = vqaddq(vecSum.val[1], vmulhq(vecInBkwd, vecCoefFwd1));
/*
* outR += *pSrc2-- * CoefB1;
*/
vecSum.val[0] = vqaddq(vecSum.val[0], vmulhq(vecInBkwd, vecCoefFwd0));
vst2q(pVecDst1, vecSum);
pVecDst1 += 16;
/*
* update fwd and backwd offsets
*/
vecStridesFwd = vecStridesFwd + (uint16_t)(modifier * 16U);
/* cannot use negative 16-bit offsets (would lead to positive 32-65K jump*/
//vecStridesBkwd = vecStridesBkwd - (uint16_t)16;
pSrc2 = pSrc2 - 16;
blkCnt--;
}
}
#else
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) */
+3 -36
View File
@@ -1,6 +1,6 @@
############################################################################
#
# Copyright (c) 2020-2021 PX4 Development Team. All rights reserved.
# Copyright (c) 2020-2022 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -31,50 +31,17 @@
#
############################################################################
set(CMSIS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5)
set(CMSIS_DSP ${CMSIS_ROOT}/CMSIS/DSP)
if(${PX4_PLATFORM} MATCHES "NuttX")
add_compile_options(-DARM_MATH_DSP)
endif()
# Disable 32-bit assembly warnings on apple silicon. Triggered by unused code only.
if(${PX4_PLATFORM} MATCHES "posix" AND APPLE AND ${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm64")
add_compile_options(-Wno-asm-operand-widths)
endif()
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-nested-externs>)
px4_add_module(
MODULE modules__gyro_fft
MAIN gyro_fft
STACK_MAIN
4096
8192
COMPILE_FLAGS
${MAX_CUSTOM_OPT_LEVEL}
-DARM_ALL_FFT_TABLES
-DARM_MATH_LOOPUNROLL
INCLUDES
${CMSIS_ROOT}/CMSIS/Core/Include
${CMSIS_DSP}/Include
SRCS
GyroFFT.cpp
GyroFFT.hpp
${CMSIS_ROOT}/CMSIS/Core/Include/cmsis_compiler.h
${CMSIS_ROOT}/CMSIS/Core/Include/cmsis_gcc.h
${CMSIS_DSP}/Include/arm_common_tables.h
${CMSIS_DSP}/Include/arm_const_structs.h
${CMSIS_DSP}/Include/arm_math.h
${CMSIS_DSP}/Source/BasicMathFunctions/arm_mult_q15.c
${CMSIS_DSP}/Source/CommonTables/arm_common_tables.c
${CMSIS_DSP}/Source/CommonTables/arm_const_structs.c
${CMSIS_DSP}/Source/SupportFunctions/arm_float_to_q15.c
${CMSIS_DSP}/Source/TransformFunctions/arm_bitreversal2.c
${CMSIS_DSP}/Source/TransformFunctions/arm_cfft_q15.c
${CMSIS_DSP}/Source/TransformFunctions/arm_cfft_radix4_q15.c
${CMSIS_DSP}/Source/TransformFunctions/arm_rfft_init_q15.c
${CMSIS_DSP}/Source/TransformFunctions/arm_rfft_q15.c
SlidingDFT.hpp
DEPENDS
px4_work_queue
)
+138 -257
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2020 - 2021 PX4 Development Team. All rights reserved.
* Copyright (c) 2020-2022 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -41,12 +41,20 @@ using namespace matrix;
GyroFFT::GyroFFT() :
ModuleParams(nullptr),
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::hp_default)
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::lp_default)
{
for (int i = 0; i < MAX_NUM_PEAKS; i++) {
_sensor_gyro_fft.peak_frequencies_x[i] = NAN;
_sensor_gyro_fft.peak_frequencies_y[i] = NAN;
_sensor_gyro_fft.peak_frequencies_z[i] = NAN;
_sensor_gyro_fft.peak_frequencies_x_raw[i] = NAN;
_sensor_gyro_fft.peak_frequencies_y_raw[i] = NAN;
_sensor_gyro_fft.peak_frequencies_z_raw[i] = NAN;
_sensor_gyro_fft.peak_magnitude_x[i] = NAN;
_sensor_gyro_fft.peak_magnitude_y[i] = NAN;
_sensor_gyro_fft.peak_magnitude_z[i] = NAN;
}
_sensor_gyro_fft_pub.advertise();
@@ -58,110 +66,17 @@ GyroFFT::~GyroFFT()
perf_free(_cycle_interval_perf);
perf_free(_fft_perf);
perf_free(_gyro_generation_gap_perf);
perf_free(_gyro_fifo_generation_gap_perf);
delete[] _gyro_data_buffer_x;
delete[] _gyro_data_buffer_y;
delete[] _gyro_data_buffer_z;
delete[] _hanning_window;
delete[] _fft_input_buffer;
delete[] _fft_outupt_buffer;
}
bool GyroFFT::init()
{
bool buffers_allocated = false;
_imu_gyro_fft_len = 64;
// arm_rfft_init_q15(&_rfft_q15, _imu_gyro_fft_len, 0, 1) manually inlined to save flash
_rfft_q15.pTwiddleAReal = (q15_t *) realCoefAQ15;
_rfft_q15.pTwiddleBReal = (q15_t *) realCoefBQ15;
_rfft_q15.ifftFlagR = 0;
_rfft_q15.bitReverseFlagR = 1;
switch (_param_imu_gyro_fft_len.get()) {
// case 128:
// buffers_allocated = AllocateBuffers<128>();
// _rfft_q15.fftLenReal = 128;
// _rfft_q15.twidCoefRModifier = 64U;
// _rfft_q15.pCfft = &arm_cfft_sR_q15_len64;
// break;
case 256:
buffers_allocated = AllocateBuffers<256>();
_rfft_q15.fftLenReal = 256;
_rfft_q15.twidCoefRModifier = 32U;
_rfft_q15.pCfft = &arm_cfft_sR_q15_len128;
break;
case 512:
buffers_allocated = AllocateBuffers<512>();
_rfft_q15.fftLenReal = 512;
_rfft_q15.twidCoefRModifier = 16U;
_rfft_q15.pCfft = &arm_cfft_sR_q15_len256;
break;
case 1024:
buffers_allocated = AllocateBuffers<1024>();
_rfft_q15.fftLenReal = 1024;
_rfft_q15.twidCoefRModifier = 8U;
_rfft_q15.pCfft = &arm_cfft_sR_q15_len512;
break;
// case 2048:
// buffers_allocated = AllocateBuffers<2048>();
// _rfft_q15.fftLenReal = 2048;
// _rfft_q15.twidCoefRModifier = 4U;
// _rfft_q15.pCfft = &arm_cfft_sR_q15_len1024;
// break;
case 4096:
buffers_allocated = AllocateBuffers<4096>();
_rfft_q15.fftLenReal = 4096;
_rfft_q15.twidCoefRModifier = 2U;
_rfft_q15.pCfft = &arm_cfft_sR_q15_len2048;
break;
// case 8192:
// buffers_allocated = AllocateBuffers<8192>();
// _rfft_q15.fftLenReal = 8192;
// _rfft_q15.twidCoefRModifier = 1U;
// _rfft_q15.pCfft = &arm_cfft_sR_q15_len4096;
// break;
default:
// otherwise default to 256
PX4_ERR("Invalid IMU_GYRO_FFT_LEN=%" PRId32 ", resetting", _param_imu_gyro_fft_len.get());
buffers_allocated = AllocateBuffers<256>();
_param_imu_gyro_fft_len.set(256);
_param_imu_gyro_fft_len.commit();
break;
if (!SensorSelectionUpdate(true)) {
ScheduleDelayed(500_ms);
}
if (buffers_allocated) {
_imu_gyro_fft_len = _param_imu_gyro_fft_len.get();
// init Hanning window
for (int n = 0; n < _imu_gyro_fft_len; n++) {
const float hanning_value = 0.5f * (1.f - cosf(2.f * M_PI_F * n / (_imu_gyro_fft_len - 1)));
arm_float_to_q15(&hanning_value, &_hanning_window[n], 1);
}
if (!SensorSelectionUpdate(true)) {
ScheduleDelayed(500_ms);
}
return true;
}
PX4_ERR("failed to allocate buffers");
delete[] _gyro_data_buffer_x;
delete[] _gyro_data_buffer_y;
delete[] _gyro_data_buffer_z;
delete[] _hanning_window;
delete[] _fft_input_buffer;
delete[] _fft_outupt_buffer;
return false;
return true;
}
bool GyroFFT::SensorSelectionUpdate(bool force)
@@ -171,41 +86,13 @@ bool GyroFFT::SensorSelectionUpdate(bool force)
_sensor_selection_sub.copy(&sensor_selection);
if ((sensor_selection.gyro_device_id != 0) && (_selected_sensor_device_id != sensor_selection.gyro_device_id)) {
// prefer sensor_gyro_fifo if available
for (uint8_t i = 0; i < MAX_SENSOR_COUNT; i++) {
uORB::SubscriptionData<sensor_gyro_fifo_s> sensor_gyro_fifo_sub{ORB_ID(sensor_gyro_fifo), i};
if (sensor_gyro_fifo_sub.get().device_id == sensor_selection.gyro_device_id) {
if (_sensor_gyro_fifo_sub.ChangeInstance(i) && _sensor_gyro_fifo_sub.registerCallback()) {
_sensor_gyro_sub.unregisterCallback();
_sensor_gyro_fifo_sub.set_required_updates(sensor_gyro_fifo_s::ORB_QUEUE_LENGTH / 2);
_selected_sensor_device_id = sensor_selection.gyro_device_id;
_gyro_fifo = true;
if (_gyro_fifo_generation_gap_perf == nullptr) {
_gyro_fifo_generation_gap_perf = perf_alloc(PC_COUNT, MODULE_NAME": gyro FIFO data gap");
}
return true;
}
}
}
// otherwise use sensor_gyro
for (uint8_t i = 0; i < MAX_SENSOR_COUNT; i++) {
uORB::SubscriptionData<sensor_gyro_s> sensor_gyro_sub{ORB_ID(sensor_gyro), i};
if (sensor_gyro_sub.get().device_id == sensor_selection.gyro_device_id) {
if (_sensor_gyro_sub.ChangeInstance(i) && _sensor_gyro_sub.registerCallback()) {
_sensor_gyro_fifo_sub.unregisterCallback();
_sensor_gyro_sub.set_required_updates(sensor_gyro_s::ORB_QUEUE_LENGTH / 2);
//_sensor_gyro_sub.set_required_updates(sensor_gyro_s::ORB_QUEUE_LENGTH - 1);
_selected_sensor_device_id = sensor_selection.gyro_device_id;
_gyro_fifo = false;
if (_gyro_generation_gap_perf == nullptr) {
_gyro_generation_gap_perf = perf_alloc(PC_COUNT, MODULE_NAME": gyro data gap");
}
return true;
}
}
@@ -241,13 +128,7 @@ void GyroFFT::VehicleIMUStatusUpdate(bool force)
// update gyro sample rate
if ((vehicle_imu_status.gyro_device_id == _selected_sensor_device_id) && (vehicle_imu_status.gyro_rate_hz > 0)) {
if (_gyro_fifo) {
_gyro_sample_rate_hz = vehicle_imu_status.gyro_raw_rate_hz;
} else {
_gyro_sample_rate_hz = vehicle_imu_status.gyro_rate_hz;
}
_gyro_sample_rate_hz = vehicle_imu_status.gyro_rate_hz;
return;
}
}
@@ -265,25 +146,22 @@ static inline float tau(float x)
return (0.25f * p1 - sqrtf(6.f) / 24.f * p2);
}
float GyroFFT::EstimatePeakFrequencyBin(q15_t fft[], int peak_index)
float GyroFFT::EstimatePeakFrequencyBin(int axis, int32_t k)
{
if (peak_index >= 2) {
if (k > 2) {
// find peak location using Quinn's Second Estimator (2020-06-14: http://dspguru.com/dsp/howtos/how-to-interpolate-fft-peak/)
float real[3] { (float)fft[peak_index - 2], (float)fft[peak_index], (float)fft[peak_index + 2] };
float imag[3] { (float)fft[peak_index - 2 + 1], (float)fft[peak_index + 1], (float)fft[peak_index + 2 + 1] };
const auto &dft = _sliding_dft[axis];
static constexpr int k = 1;
const float divider = (real[k] * real[k] + imag[k] * imag[k]);
const float divider = (dft.dft(k).real() * dft.dft(k).real() + dft.dft(k).imag() * dft.dft(k).imag());
// ap = (X[k + 1].r * X[k].r + X[k+1].i * X[k].i) / (X[k].r * X[k].r + X[k].i * X[k].i)
float ap = (real[k + 1] * real[k] + imag[k + 1] * imag[k]) / divider;
float ap = (dft.dft(k + 1).real() * dft.dft(k).real() + dft.dft(k + 1).imag() * dft.dft(k).imag()) / divider;
// dp = -ap / (1 ap)
float dp = -ap / (1.f - ap);
// am = (X[k - 1].r * X[k].r + X[k 1].i * X[k].i) / (X[k].r * X[k].r + X[k].i * X[k].i)
float am = (real[k - 1] * real[k] + imag[k - 1] * imag[k]) / divider;
float am = (dft.dft(k - 1).real() * dft.dft(k).real() + dft.dft(k - 1).imag() * dft.dft(k).imag()) / divider;
// dm = am / (1 am)
float dm = am / (1.f - am);
@@ -292,7 +170,9 @@ float GyroFFT::EstimatePeakFrequencyBin(q15_t fft[], int peak_index)
float d = (dp + dm) / 2.f + tau(dp * dp) - tau(dm * dm);
// k = k + d
return peak_index + 2.f * d;
float adjusted_bin = k + d;
return adjusted_bin;
}
return NAN;
@@ -302,7 +182,6 @@ void GyroFFT::Run()
{
if (should_exit()) {
_sensor_gyro_sub.unregisterCallback();
_sensor_gyro_fifo_sub.unregisterCallback();
exit_and_cleanup();
return;
}
@@ -325,64 +204,26 @@ void GyroFFT::Run()
const bool selection_updated = SensorSelectionUpdate();
VehicleIMUStatusUpdate(selection_updated);
// reset
_fft_updated = false;
// run on sensor gyro updates
sensor_gyro_s sensor_gyro;
if (_gyro_fifo) {
// run on sensor gyro fifo updates
sensor_gyro_fifo_s sensor_gyro_fifo;
while (_sensor_gyro_fifo_sub.update(&sensor_gyro_fifo)) {
if (_sensor_gyro_fifo_sub.get_last_generation() != _gyro_last_generation + 1) {
// force reset if we've missed a sample
_fft_buffer_index[0] = 0;
_fft_buffer_index[1] = 0;
_fft_buffer_index[2] = 0;
perf_count(_gyro_fifo_generation_gap_perf);
}
_gyro_last_generation = _sensor_gyro_fifo_sub.get_last_generation();
if (fabsf(sensor_gyro_fifo.scale - _fifo_last_scale) > FLT_EPSILON) {
// force reset if scale has changed
_fft_buffer_index[0] = 0;
_fft_buffer_index[1] = 0;
_fft_buffer_index[2] = 0;
_fifo_last_scale = sensor_gyro_fifo.scale;
}
int16_t *input[] {sensor_gyro_fifo.x, sensor_gyro_fifo.y, sensor_gyro_fifo.z};
Update(sensor_gyro_fifo.timestamp_sample, input, sensor_gyro_fifo.samples);
while (_sensor_gyro_sub.update(&sensor_gyro)) {
if (_sensor_gyro_sub.get_last_generation() != _gyro_last_generation + 1) {
// force reset if we've missed a sample
perf_count(_gyro_generation_gap_perf);
}
} else {
// run on sensor gyro fifo updates
sensor_gyro_s sensor_gyro;
_gyro_last_generation = _sensor_gyro_sub.get_last_generation();
while (_sensor_gyro_sub.update(&sensor_gyro)) {
if (_sensor_gyro_sub.get_last_generation() != _gyro_last_generation + 1) {
// force reset if we've missed a sample
_fft_buffer_index[0] = 0;
_fft_buffer_index[1] = 0;
_fft_buffer_index[2] = 0;
perf_count(_gyro_generation_gap_perf);
}
_gyro_last_generation = _sensor_gyro_sub.get_last_generation();
const float gyro_scale = math::radians(1000.f); // arbitrary scaling float32 rad/s -> raw int16
int16_t gyro_x[1] {(int16_t)roundf(sensor_gyro.x * gyro_scale)};
int16_t gyro_y[1] {(int16_t)roundf(sensor_gyro.y * gyro_scale)};
int16_t gyro_z[1] {(int16_t)roundf(sensor_gyro.z * gyro_scale)};
int16_t *input[] {gyro_x, gyro_y, gyro_z};
Update(sensor_gyro.timestamp_sample, input, 1);
}
perf_begin(_fft_perf);
_sliding_dft[0].update(sensor_gyro.x);
_sliding_dft[1].update(sensor_gyro.y);
_sliding_dft[2].update(sensor_gyro.z);
perf_end(_fft_perf);
}
Update(sensor_gyro.timestamp_sample);
if (_publish) {
Publish();
_publish = false;
@@ -391,45 +232,38 @@ void GyroFFT::Run()
perf_end(_cycle_perf);
}
void GyroFFT::Update(const hrt_abstime &timestamp_sample, int16_t *input[], uint8_t N)
void GyroFFT::Update(const hrt_abstime &timestamp_sample)
{
q15_t *gyro_data_buffer[] {_gyro_data_buffer_x, _gyro_data_buffer_y, _gyro_data_buffer_z};
//float *peak_frequencies_raw[] {_sensor_gyro_fft.peak_frequencies_x_raw, _sensor_gyro_fft.peak_frequencies_y_raw, _sensor_gyro_fft.peak_frequencies_z_raw};
//float *peak_magnitude_out[] {_sensor_gyro_fft.peak_magnitude_x, _sensor_gyro_fft.peak_magnitude_y, _sensor_gyro_fft.peak_magnitude_z};
// wipe TODO: temporary
memset(&_sensor_gyro_fft.peak_frequencies_x_raw, 0, sizeof(_sensor_gyro_fft.peak_frequencies_x_raw));
memset(&_sensor_gyro_fft.peak_frequencies_y_raw, 0, sizeof(_sensor_gyro_fft.peak_frequencies_y_raw));
memset(&_sensor_gyro_fft.peak_frequencies_z_raw, 0, sizeof(_sensor_gyro_fft.peak_frequencies_z_raw));
memset(&_sensor_gyro_fft.peak_magnitude_x, 0, sizeof(_sensor_gyro_fft.peak_magnitude_x));
memset(&_sensor_gyro_fft.peak_magnitude_y, 0, sizeof(_sensor_gyro_fft.peak_magnitude_y));
memset(&_sensor_gyro_fft.peak_magnitude_z, 0, sizeof(_sensor_gyro_fft.peak_magnitude_z));
for (int axis = 0; axis < 3; axis++) {
int &buffer_index = _fft_buffer_index[axis];
for (int n = 0; n < N; n++) {
if (buffer_index < _imu_gyro_fft_len) {
// convert int16_t -> q15_t (scaling isn't relevant)
gyro_data_buffer[axis][buffer_index] = input[axis][n] / 2;
buffer_index++;
}
// if we have enough samples begin processing, but only one FFT per cycle
if ((buffer_index >= _imu_gyro_fft_len) && !_fft_updated) {
perf_begin(_fft_perf);
arm_mult_q15(gyro_data_buffer[axis], _hanning_window, _fft_input_buffer, _imu_gyro_fft_len);
arm_rfft_q15(&_rfft_q15, _fft_input_buffer, _fft_outupt_buffer);
_fft_updated = true;
FindPeaks(timestamp_sample, axis, _fft_outupt_buffer);
// reset
// shift buffer (3/4 overlap)
const int overlap_start = _imu_gyro_fft_len / 4;
memmove(&gyro_data_buffer[axis][0], &gyro_data_buffer[axis][overlap_start], sizeof(q15_t) * overlap_start * 3);
buffer_index = overlap_start * 3;
perf_end(_fft_perf);
}
// if we have enough samples begin processing
if (_sliding_dft[axis].data_valid()) {
_fft_updated = true;
FindPeaks(timestamp_sample, axis);
}
}
}
void GyroFFT::FindPeaks(const hrt_abstime &timestamp_sample, int axis, q15_t *fft_outupt_buffer)
void GyroFFT::FindPeaks(const hrt_abstime &timestamp_sample, int axis)
{
float *peak_frequencies_raw[] {_sensor_gyro_fft.peak_frequencies_x_raw, _sensor_gyro_fft.peak_frequencies_y_raw, _sensor_gyro_fft.peak_frequencies_z_raw};
float *peak_magnitude_out[] {_sensor_gyro_fft.peak_magnitude_x, _sensor_gyro_fft.peak_magnitude_y, _sensor_gyro_fft.peak_magnitude_z};
const float resolution_hz = _gyro_sample_rate_hz / _imu_gyro_fft_len;
// sum total energy across all used buckets for SNR
@@ -439,31 +273,58 @@ void GyroFFT::FindPeaks(const hrt_abstime &timestamp_sample, int axis, q15_t *ff
uint16_t raw_peak_index[MAX_NUM_PEAKS] {};
float peak_magnitude[MAX_NUM_PEAKS] {};
// FFT output buffer is ordered [real[0], imag[0], real[1], imag[1], real[2], imag[2] ... real[(N/2)-1], imag[(N/2)-1]
for (uint16_t bucket_index = 0; bucket_index < (2 * _imu_gyro_fft_len - 1); bucket_index = bucket_index + 2) {
float peak_magnitudes_all[FFT_LEN] {};
const float freq_hz = (bucket_index / 2) * resolution_hz;
for (int bucket_index = 1; bucket_index < _imu_gyro_fft_len / 2; bucket_index++) {
if ((bucket_index > 0) && (bucket_index < (_imu_gyro_fft_len - 1))
&& (freq_hz >= _param_imu_gyro_fft_min.get())
&& (freq_hz <= _param_imu_gyro_fft_max.get())) {
const float real = _sliding_dft[axis].dft(bucket_index).real();
const float imag = _sliding_dft[axis].dft(bucket_index).imag();
const float real = fft_outupt_buffer[bucket_index];
const float imag = fft_outupt_buffer[bucket_index + 1];
const float fft_magnitude = sqrtf(real * real + imag * imag);
const float fft_magnitude_squared = real * real + imag * imag;
bin_mag_sum += fft_magnitude_squared;
peak_magnitudes_all[bucket_index] = fft_magnitude;
for (int i = 0; i < MAX_NUM_PEAKS; i++) {
if (fft_magnitude_squared > peak_magnitude[i]) {
peak_magnitude[i] = fft_magnitude_squared;
raw_peak_index[i] = bucket_index;
break;
}
bin_mag_sum += fft_magnitude;
}
for (int i = 0; i < MAX_NUM_PEAKS; i++) {
float largest_peak = 0;
int largest_peak_index = 0;
for (int bucket_index = 1; bucket_index < _imu_gyro_fft_len / 2; bucket_index++) {
const float freq = (_gyro_sample_rate_hz * bucket_index / _imu_gyro_fft_len);
if ((peak_magnitudes_all[bucket_index] > largest_peak)
&& (freq >= _param_imu_gyro_fft_min.get())
&& (freq <= _param_imu_gyro_fft_max.get())) {
largest_peak = peak_magnitudes_all[bucket_index];
largest_peak_index = bucket_index;
}
}
if (largest_peak_index != 0) {
raw_peak_index[i] = largest_peak_index;
peak_magnitude[i] = peak_magnitudes_all[largest_peak_index];
// remove peak + sides (included in frequency estimate later)
peak_magnitudes_all[largest_peak_index - 1] = 0;
peak_magnitudes_all[largest_peak_index] = 0;
peak_magnitudes_all[largest_peak_index + 1] = 0;
// tmp logging
peak_frequencies_raw[axis][i] = largest_peak_index * resolution_hz;
peak_magnitude_out[axis][i] = peak_magnitude[i];
}
}
_sensor_gyro_fft.total_energy[axis] = bin_mag_sum;
// keep if peak has been previously seen and SNR > MIN_SNR
// or
// peak has SNR > MIN_SNR_INITIAL
@@ -475,28 +336,47 @@ void GyroFFT::FindPeaks(const hrt_abstime &timestamp_sample, int axis, q15_t *ff
float *peak_frequencies_publish[] { _sensor_gyro_fft.peak_frequencies_x, _sensor_gyro_fft.peak_frequencies_y, _sensor_gyro_fft.peak_frequencies_z };
float peak_frequencies_prev[MAX_NUM_PEAKS];
for (int i = 0; i < MAX_NUM_PEAKS; i++) {
peak_frequencies_prev[i] = peak_frequencies_publish[axis][i];
}
for (int peak_new = 0; peak_new < MAX_NUM_PEAKS; peak_new++) {
if (raw_peak_index[peak_new] > 0) {
const float snr = 10.f * log10f((_imu_gyro_fft_len - 1) * peak_magnitude[peak_new] /
(bin_mag_sum - peak_magnitude[peak_new]));
// estimate adjusted frequency bin, magnitude, and SNR for the largest peaks found
const float adjusted_bin = EstimatePeakFrequencyBin(axis, raw_peak_index[peak_new]);
if (snr > MIN_SNR) {
// estimate adjusted frequency bin, magnitude, and SNR for the largest peaks found
const float adjusted_bin = EstimatePeakFrequencyBin(fft_outupt_buffer, raw_peak_index[peak_new]);
const float freq_adjusted = (adjusted_bin / 2.f) * resolution_hz;
if (PX4_ISFINITE(adjusted_bin)) {
const float freq_adjusted = (_gyro_sample_rate_hz * adjusted_bin / _imu_gyro_fft_len);
if (PX4_ISFINITE(adjusted_bin) && PX4_ISFINITE(freq_adjusted)
&& (freq_adjusted > _param_imu_gyro_fft_min.get())
&& (freq_adjusted < _param_imu_gyro_fft_max.get())) {
// PX4_INFO("bin: %.1f adjusted: %.1f freq adjusted: %.1f", (double)raw_peak_index[peak_new], (double)adjusted_bin,
// (double)freq_adjusted);
const float snr = 10.f * log10f((_imu_gyro_fft_len - 1) * peak_magnitude[peak_new] /
(bin_mag_sum - peak_magnitude[peak_new]));
if (PX4_ISFINITE(freq_adjusted)
&& (snr > MIN_SNR)
&& (freq_adjusted >= _param_imu_gyro_fft_min.get())
&& (freq_adjusted <= _param_imu_gyro_fft_max.get())) {
// only keep if we're already tracking this frequency or if the SNR is significant
for (int peak_prev = 0; peak_prev < MAX_NUM_PEAKS; peak_prev++) {
if ((snr > _param_imu_gyro_fft_snr.get())
|| (fabsf(freq_adjusted - peak_frequencies_publish[axis][peak_prev]) < (resolution_hz * 0.5f))) {
bool snr_acceptable = (snr > _param_imu_gyro_fft_snr.get());
bool peak_close = (fabsf(freq_adjusted - peak_frequencies_prev[peak_prev]) < (resolution_hz * 0.5f));
if (snr_acceptable || peak_close) {
// keep
peak_frequencies[num_peaks_found] = freq_adjusted;
peak_snr[num_peaks_found] = snr;
// remove
if (peak_close) {
peak_frequencies_prev[peak_prev] = NAN;
}
num_peaks_found++;
break;
}
@@ -567,6 +447,7 @@ void GyroFFT::UpdateOutput(const hrt_abstime &timestamp_sample, int axis, float
if (PX4_ISFINITE(smallest_diff) && (smallest_diff > 0)) {
// smallest diff found, copy newly found peak into same slot previously published
float peak_frequency = _median_filter[axis][closest_prev_peak].apply(peak_frequencies[closest_new_peak]);
//float peak_frequency = peak_frequencies[closest_new_peak];
if (peak_frequency > 0) {
peak_frequencies_publish[axis][closest_prev_peak] = peak_frequency;
@@ -618,6 +499,7 @@ void GyroFFT::UpdateOutput(const hrt_abstime &timestamp_sample, int axis, float
if (oldest_slot >= 0) {
// copy peak to output slot
float peak_frequency = _median_filter[axis][oldest_slot].apply(peak_frequencies[peak_new]);
//float peak_frequency = peak_frequencies[peak_new];
if (peak_frequency > 0) {
peak_frequencies_publish[axis][oldest_slot] = peak_frequency;
@@ -672,7 +554,6 @@ int GyroFFT::print_status()
perf_print_counter(_cycle_interval_perf);
perf_print_counter(_fft_perf);
perf_print_counter(_gyro_generation_gap_perf);
perf_print_counter(_gyro_fifo_generation_gap_perf);
return 0;
}
+13 -46
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2020-2021 PX4 Development Team. All rights reserved.
* Copyright (c) 2020-2022 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,8 +31,7 @@
*
****************************************************************************/
#ifndef GYRO_FFT_HPP
#define GYRO_FFT_HPP
#pragma once
#include <lib/mathlib/math/filter/MedianFilter.hpp>
#include <lib/matrix/matrix/math.hpp>
@@ -49,12 +48,10 @@
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/sensor_gyro.h>
#include <uORB/topics/sensor_gyro_fft.h>
#include <uORB/topics/sensor_gyro_fifo.h>
#include <uORB/topics/sensor_selection.h>
#include <uORB/topics/vehicle_imu_status.h>
#include "arm_math.h"
#include "arm_const_structs.h"
#include "SlidingDFT.hpp"
using namespace time_literals;
@@ -85,31 +82,15 @@ private:
sensor_gyro_fft_s::peak_frequencies_x[0]);
void Run() override;
inline void FindPeaks(const hrt_abstime &timestamp_sample, int axis, q15_t *fft_outupt_buffer);
inline float EstimatePeakFrequencyBin(q15_t fft[], int peak_index);
inline void FindPeaks(const hrt_abstime &timestamp_sample, int axis);
inline float EstimatePeakFrequencyBin(int axis, int32_t k);
inline void Publish();
bool SensorSelectionUpdate(bool force = false);
void Update(const hrt_abstime &timestamp_sample, int16_t *input[], uint8_t N);
void Update(const hrt_abstime &timestamp_sample);
inline void UpdateOutput(const hrt_abstime &timestamp_sample, int axis, float peak_frequencies[MAX_NUM_PEAKS],
float peak_snr[MAX_NUM_PEAKS], int num_peaks_found);
void VehicleIMUStatusUpdate(bool force = false);
template<size_t N>
bool AllocateBuffers()
{
_gyro_data_buffer_x = new q15_t[N];
_gyro_data_buffer_y = new q15_t[N];
_gyro_data_buffer_z = new q15_t[N];
_hanning_window = new q15_t[N];
_fft_input_buffer = new q15_t[N];
_fft_outupt_buffer = new q15_t[N * 2];
return (_gyro_data_buffer_x && _gyro_data_buffer_y && _gyro_data_buffer_z
&& _hanning_window
&& _fft_input_buffer
&& _fft_outupt_buffer);
}
uORB::Publication<sensor_gyro_fft_s> _sensor_gyro_fft_pub{ORB_ID(sensor_gyro_fft)};
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
@@ -118,32 +99,15 @@ private:
uORB::Subscription _vehicle_imu_status_sub{ORB_ID(vehicle_imu_status)};
uORB::SubscriptionCallbackWorkItem _sensor_gyro_sub{this, ORB_ID(sensor_gyro)};
uORB::SubscriptionCallbackWorkItem _sensor_gyro_fifo_sub{this, ORB_ID(sensor_gyro_fifo)};
perf_counter_t _cycle_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")};
perf_counter_t _cycle_interval_perf{perf_alloc(PC_INTERVAL, MODULE_NAME": cycle interval")};
perf_counter_t _fft_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": FFT")};
perf_counter_t _gyro_generation_gap_perf{nullptr};
perf_counter_t _gyro_fifo_generation_gap_perf{nullptr};
perf_counter_t _gyro_generation_gap_perf{perf_alloc(PC_COUNT, MODULE_NAME": gyro data gap")};
uint32_t _selected_sensor_device_id{0};
bool _gyro_fifo{false};
arm_rfft_instance_q15 _rfft_q15;
q15_t *_gyro_data_buffer_x{nullptr};
q15_t *_gyro_data_buffer_y{nullptr};
q15_t *_gyro_data_buffer_z{nullptr};
q15_t *_hanning_window{nullptr};
q15_t *_fft_input_buffer{nullptr};
q15_t *_fft_outupt_buffer{nullptr};
float _gyro_sample_rate_hz{8000}; // 8 kHz default
float _fifo_last_scale{0};
int _fft_buffer_index[3] {};
float _gyro_sample_rate_hz{800};
unsigned _gyro_last_generation{0};
@@ -153,11 +117,15 @@ private:
hrt_abstime _last_update[3][MAX_NUM_PEAKS] {};
int32_t _imu_gyro_fft_len{256};
static constexpr int FFT_LEN = 64;
int32_t _imu_gyro_fft_len{FFT_LEN};
bool _fft_updated{false};
bool _publish{false};
SlidingDFT<FFT_LEN> _sliding_dft[3];
DEFINE_PARAMETERS(
(ParamInt<px4::params::IMU_GYRO_FFT_LEN>) _param_imu_gyro_fft_len,
(ParamFloat<px4::params::IMU_GYRO_FFT_MIN>) _param_imu_gyro_fft_min,
@@ -166,4 +134,3 @@ private:
)
};
#endif // !GYRO_FFT_HPP
+317
View File
@@ -0,0 +1,317 @@
/**
Sliding discrete Fourier transform (C++)
====
This code efficiently computes discrete Fourier transforms (DFTs) from a
continuous sequence of input values. It is a recursive algorithm that updates
the DFT when each new time-domain measurement arrives, effectively applying a
sliding window over the last *N* samples. This implementation applies the
Hanning window in order to minimise spectral leakage.
The update step has computational complexity *O(N)*. If a new DFT is required
every *M* samples, and *M* < log2(*N*), then this approach is more efficient
that recalculating the DFT from scratch each time.
This is a header-only C++ library. Simply copy sliding_dft.hpp into your
project, and use it as follows:
// Use double precision arithmetic and a 512-length DFT
static SlidingDFT<double, 512> dft;
// avoid allocating on the stack because the object is large
// When a new time sample arrives, update the DFT with:
dft.update(x);
// After at least 512 samples have been processed:
std::complex<double> DC_bin = dft.dft[0];
Your application should call update() as each time domain sample arrives. Output
data is an array of `std::complex` values in the `dft` field. The length of this
array is the length of the DFT.
The output data is not valid until at least *N* samples have been processed. You
can detect this using the `is_data_valid()` method, or by storing the return
value of the `update()` method.
This is a header-only C++ library. Simply copy sliding_dft.hpp into your
project. The included CMakeLists.txt is for building the testbench.
Implementation details
----
See references [1, 2] for an overview of sliding DFT algorithms. A damping
factor is used to improve stability in the face of numerical rounding errors. If
you experience stability issues, reduce `dft.damping_factor`. It should be
slightly less than one.
Windowing is done using a Hanning window, computed in the frequency domain [1].
[1] E. Jacobsen and R. Lyons, “The Sliding DFT,” IEEE Signal Process. Mag., vol. 20, no. 2, pp. 7480, Mar. 2003.
[2] E. Jacobsen and R. Lyons, “An Update to the Sliding DFT,” IEEE Signal Process. Mag., vol. 21, no. 1, pp. 110-111, 2004.
MIT License
----
Copyright (c) 2016 Bronson Philippa
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <math.h>
class Complex;
Complex operator*(const Complex &, const Complex &);
Complex operator/(const Complex &, const Complex &);
Complex operator-(const Complex &, const Complex &);
Complex operator-(const Complex &, const float &);
class Complex
{
public:
Complex(float real = 0.f, float imag = 0.f) : _real(real), _imag(imag) {}
Complex(const Complex &c) : _real(c.real()), _imag(c.imag()) {}
float real() const { return _real; }
float imag() const { return _imag; }
float norm() const { return _real * _real + _imag * _imag; }
Complex &operator= (const float &re) { _real = re; _imag = 0.f; return *this;}
Complex &operator+=(const float &re) { _real += re; return *this;}
Complex &operator-=(const float &re) { _real -= re; return *this;}
Complex &operator*=(const float &re) { _real *= re; _imag *= re; return *this;}
Complex &operator/=(const float &re) { _real /= re; _imag /= re; return *this;}
Complex &operator= (const Complex &c)
{
_real = c.real();
_imag = c.imag();
return *this;
}
Complex &operator+=(const Complex &c)
{
_real += c.real();
_imag += c.imag();
return *this;
}
Complex &operator-=(const Complex &c)
{
_real -= c.real();
_imag -= c.imag();
return *this;
}
Complex &operator*=(const Complex &c)
{
*this = *this * Complex(c.real(), c.imag());
return *this;
}
Complex &operator/=(const Complex &c)
{
*this = *this / Complex(c.real(), c.imag());
return *this;
}
private:
float _real{0.f};
float _imag{0.f};
};
Complex operator+(const Complex &x, const Complex &y)
{
Complex t{x};
t += y;
return t;
}
Complex operator*(const Complex &z, const Complex &w)
{
float a = z.real();
float b = z.imag();
float c = w.real();
float d = w.imag();
float ac = a * c;
float bd = b * d;
float ad = a * d;
float bc = b * c;
float x = ac - bd;
float y = ad + bc;
if (isnan(x) && isnan(y)) {
bool recalc = false;
if (isinf(a) || isinf(b)) {
a = copysign(isinf(a) ? float(1) : float(0), a);
b = copysign(isinf(b) ? float(1) : float(0), b);
if (isnan(c)) {
c = copysign(float(0), c);
}
if (isnan(d)) {
d = copysign(float(0), d);
}
recalc = true;
}
if (isinf(c) || isinf(d)) {
c = copysign(isinf(c) ? float(1) : float(0), c);
d = copysign(isinf(d) ? float(1) : float(0), d);
if (isnan(a)) {
a = copysign(float(0), a);
}
if (isnan(b)) {
b = copysign(float(0), b);
}
recalc = true;
}
if (!recalc && (isinf(ac) || isinf(bd) || isinf(ad) || isinf(bc))) {
if (isnan(a)) {
a = copysign(float(0), a);
}
if (isnan(b)) {
b = copysign(float(0), b);
}
if (isnan(c)) {
c = copysign(float(0), c);
}
if (isnan(d)) {
d = copysign(float(0), d);
}
recalc = true;
}
if (recalc) {
x = float(INFINITY) * (a * c - b * d);
y = float(INFINITY) * (a * d + b * c);
}
}
return Complex(x, y);
}
Complex operator-(const Complex &x, const Complex &y)
{
Complex t(x);
t -= y;
return t;
}
Complex operator-(const Complex &x, const float &y)
{
Complex t(x);
t -= y;
return t;
}
template <size_t DFT_Length>
class SlidingDFT
{
public:
SlidingDFT()
{
// Compute the twiddle factors, and zero the x and S arrays
for (size_t k = 0; k < DFT_Length; k++) {
float factor = (2.f * (float)M_PI) * k / DFT_Length;
_twiddle[k] = Complex(cosf(factor), sinf(factor));
}
}
/// Determine whether the output data is valid
bool data_valid() const { return _data_valid; }
/// Update the calculation with a new sample
/// Returns true if the data are valid (because enough samples have been
/// presented), or false if the data are invalid.
bool update(float new_x)
{
// Update the storage of the time domain values
const float old_x = _x[_x_index];
_x[_x_index] = new_x;
// Update the DFT
const float r = _damping_factor;
const float r_to_N = powf(r, (float)DFT_Length);
for (size_t k = 0; k < DFT_Length; k++) {
_S[k] = _twiddle[k] * (r * _S[k] - r_to_N * old_x + new_x);
}
// Apply the Hanning window
_dft[0] = 0.5f * _S[0] - 0.25f * (_S[DFT_Length - 1] + _S[1]);
for (size_t k = 1; k < (DFT_Length - 1); k++) {
_dft[k] = 0.5f * _S[k] - 0.25f * (_S[k - 1] + _S[k + 1]);
}
_dft[DFT_Length - 1] = 0.5f * _S[DFT_Length - 1] - 0.25f * (_S[DFT_Length - 2] + _S[0]);
// Increment the counter
_x_index++;
if (_x_index >= DFT_Length) {
_data_valid = true;
_x_index = 0;
}
return _data_valid;
}
const auto &dft(int index) const { return _dft[index]; }
private:
/// Frequency domain values (windowed)
Complex _dft[DFT_Length] {};
/// A damping factor introduced into the recursive DFT algorithm to guarantee stability.
float _damping_factor{0.9999f};
/// Are the frequency domain values valid? (i.e. have at elast DFT_Length data points been seen?)
bool _data_valid{false};
/// Time domain samples are stored in this circular buffer.
float _x[DFT_Length] {};
/// Index of the next item in the buffer to be used. Equivalently, the number of samples that have been seen so far modulo DFT_Length.
size_t _x_index{0};
/// Twiddle factors for the update algorithm
Complex _twiddle[DFT_Length] {};
/// Frequency domain values (unwindowed!)
Complex _S[DFT_Length] {};
};
+1 -1
View File
@@ -87,7 +87,7 @@ void LoggedTopics::add_default_topics()
add_topic("safety");
add_topic("sensor_combined");
add_optional_topic("sensor_correction");
add_optional_topic("sensor_gyro_fft", 50);
add_optional_topic("sensor_gyro_fft", 0);
add_topic("sensor_selection");
add_topic("sensors_status_imu", 200);
add_topic("system_power", 500);