/* ---------------------------------------------------------------------- * Project: CMSIS DSP Library * Title: arm_fir_f64.c * Description: Floating-point FIR filter processing function * * $Date: 03 June 2022 * $Revision: V1.10.1 * * Target Processor: Cortex-M and Cortex-A cores * -------------------------------------------------------------------- */ /* * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "dsp/filtering_functions.h" /** @ingroup groupFilters */ /** @addtogroup FIR @{ */ /** @brief Processing function for floating-point FIR filter. @param[in] S points to an instance of the floating-point FIR filter structure @param[in] pSrc points to the block of input data @param[out] pDst points to the block of output data @param[in] blockSize number of samples to process */ #if defined(ARM_MATH_NEON) && defined(__aarch64__) ARM_DSP_ATTRIBUTE void arm_fir_f64( const arm_fir_instance_f64 * S, const float64_t * pSrc, float64_t * pDst, uint32_t blockSize) { float64_t *pState = S->pState; /* State pointer */ const float64_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ float64_t *pStateCurnt; /* Points to the current sample of the state */ float64_t *px; /* Temporary pointer for state buffer */ const float64_t *pb; /* Temporary pointer for coefficient buffer */ float64x2_t pxV; float64x2_t pbV; float64x2_t acc0V; float64_t acc0; /* Accumulator */ uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ uint32_t i, tapCnt, blkCnt; /* Loop counters */ /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ /* pStateCurnt points to the location where the new input data should be written */ pStateCurnt = &(S->pState[(numTaps - 1U)]); /* Initialize blkCnt with number of taps */ blkCnt = blockSize; while (blkCnt > 0U) { /* Copy one sample at a time into state buffer */ *pStateCurnt++ = *pSrc++; /* Set the accumulator to zero */ acc0 = 0.; acc0V = vdupq_n_f64(0.0); /* Initialize state pointer */ px = pState; /* Initialize Coefficient pointer */ pb = pCoeffs; i = numTaps >> 1U; /* Perform the multiply-accumulates */ while (i > 0U) { /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ pxV = vld1q_f64(px); pbV = vld1q_f64(pb); acc0V = vmlaq_f64(acc0V, pxV, pbV); px+=2; pb+=2; i--; } acc0 = vaddvq_f64(acc0V); i = numTaps%2 ; while(i >0U) { acc0+= *px++ * *pb++ ; i--; } /* Store result in destination buffer. */ *pDst++ = acc0; /* Advance state pointer by 1 for the next sample */ pState = pState + 1U; /* Decrement loop counter */ blkCnt--; } /* Processing is complete. Now copy the last numTaps - 1 samples to the start of the state buffer. This prepares the state buffer for the next function call. */ /* Points to the start of the state buffer */ pStateCurnt = S->pState; /* Initialize tapCnt with number of taps */ tapCnt = (numTaps - 1U); /* Copy remaining data */ while (tapCnt > 0U) { *pStateCurnt++ = *pState++; /* Decrement loop counter */ tapCnt--; } } #else ARM_DSP_ATTRIBUTE void arm_fir_f64( const arm_fir_instance_f64 * S, const float64_t * pSrc, float64_t * pDst, uint32_t blockSize) { float64_t *pState = S->pState; /* State pointer */ const float64_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ float64_t *pStateCurnt; /* Points to the current sample of the state */ float64_t *px; /* Temporary pointer for state buffer */ const float64_t *pb; /* Temporary pointer for coefficient buffer */ float64_t acc0; /* Accumulator */ uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ uint32_t i, tapCnt, blkCnt; /* Loop counters */ /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ /* pStateCurnt points to the location where the new input data should be written */ pStateCurnt = &(S->pState[(numTaps - 1U)]); /* Initialize blkCnt with number of taps */ blkCnt = blockSize; while (blkCnt > 0U) { /* Copy one sample at a time into state buffer */ *pStateCurnt++ = *pSrc++; /* Set the accumulator to zero */ acc0 = 0.; /* Initialize state pointer */ px = pState; /* Initialize Coefficient pointer */ pb = pCoeffs; i = numTaps; /* Perform the multiply-accumulates */ while (i > 0U) { /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ acc0 += *px++ * *pb++; i--; } /* Store result in destination buffer. */ *pDst++ = acc0; /* Advance state pointer by 1 for the next sample */ pState = pState + 1U; /* Decrement loop counter */ blkCnt--; } /* Processing is complete. Now copy the last numTaps - 1 samples to the start of the state buffer. This prepares the state buffer for the next function call. */ /* Points to the start of the state buffer */ pStateCurnt = S->pState; /* Initialize tapCnt with number of taps */ tapCnt = (numTaps - 1U); /* Copy remaining data */ while (tapCnt > 0U) { *pStateCurnt++ = *pState++; /* Decrement loop counter */ tapCnt--; } } #endif /** * @} end of FIR group */