1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_fir_init_q15.c
4  * Description:  Q15 FIR filter initialization function
5  *
6  * $Date:        23 April 2021
7  * $Revision:    V1.9.0
8  *
9  * Target Processor: Cortex-M and Cortex-A cores
10  * -------------------------------------------------------------------- */
11 /*
12  * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13  *
14  * SPDX-License-Identifier: Apache-2.0
15  *
16  * Licensed under the Apache License, Version 2.0 (the License); you may
17  * not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19  *
20  * www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 #include "dsp/filtering_functions.h"
30 
31 /**
32   @ingroup groupFilters
33  */
34 
35 /**
36   @addtogroup FIR
37   @{
38  */
39 
40 /**
41   @brief         Initialization function for the Q15 FIR filter.
42   @param[in,out] S          points to an instance of the Q15 FIR filter structure.
43   @param[in]     numTaps    number of filter coefficients in the filter. Must be even and greater than or equal to 4.
44   @param[in]     pCoeffs    points to the filter coefficients buffer.
45   @param[in]     pState     points to the state buffer.
46   @param[in]     blockSize  number of samples processed per call.
47   @return        execution status
48                    - \ref ARM_MATH_SUCCESS        : Operation successful
49                    - \ref ARM_MATH_ARGUMENT_ERROR : <code>numTaps</code> is not greater than or equal to 4 and even
50 
51   @par           Details
52                    <code>pCoeffs</code> points to the array of filter coefficients stored in time reversed order:
53   <pre>
54       {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}
55   </pre>
56                    Note that <code>numTaps</code> must be even and greater than or equal to 4.
57                    To implement an odd length filter simply increase <code>numTaps</code> by 1 and set the last coefficient to zero.
58                    For example, to implement a filter with <code>numTaps=3</code> and coefficients
59   <pre>
60       {0.3, -0.8, 0.3}
61   </pre>
62                    set <code>numTaps=4</code> and use the coefficients:
63   <pre>
64       {0.3, -0.8, 0.3, 0}.
65   </pre>
66                    Similarly, to implement a two point filter
67   <pre>
68       {0.3, -0.3}
69   </pre>
70                    set <code>numTaps=4</code> and use the coefficients:
71   <pre>
72       {0.3, -0.3, 0, 0}.
73   </pre>
74                    <code>pState</code> points to the array of state variables.
75                    <code>pState</code> is of length <code>numTaps+blockSize</code>, when running on Cortex-M4 and Cortex-M3  and is of length <code>numTaps+blockSize-1</code>, when running on Cortex-M0 where <code>blockSize</code> is the number of input samples processed by each call to <code>arm_fir_q15()</code>.
76 
77   @par          Initialization of Helium version
78                    For Helium version the array of coefficients must be a multiple of 8 (8a) even if less
79                    then 8a coefficients are defined in the FIR. The additional coefficients
80                    (8a - numTaps) must be set to 0.
81                    numTaps is still set to its right value in the init function. It means that
82                    the implementation may require to read more coefficients due to the vectorization and
83                    to avoid having to manage too many different cases in the code.
84  */
85 
arm_fir_init_q15(arm_fir_instance_q15 * S,uint16_t numTaps,const q15_t * pCoeffs,q15_t * pState,uint32_t blockSize)86 ARM_DSP_ATTRIBUTE arm_status arm_fir_init_q15(
87         arm_fir_instance_q15 * S,
88         uint16_t numTaps,
89   const q15_t * pCoeffs,
90         q15_t * pState,
91         uint32_t blockSize)
92 {
93   arm_status status;
94 
95 #if defined (ARM_MATH_DSP)
96 
97   /* The Number of filter coefficients in the filter must be even and at least 4 */
98   if (numTaps & 0x1U)
99   {
100     status = ARM_MATH_ARGUMENT_ERROR;
101   }
102   else
103   {
104     /* Assign filter taps */
105     S->numTaps = numTaps;
106 
107     /* Assign coefficient pointer */
108     S->pCoeffs = pCoeffs;
109 
110     /* Clear the state buffer.  The size is always (blockSize + numTaps ) */
111     memset(pState, 0, (numTaps + (blockSize)) * sizeof(q15_t));
112 
113     /* Assign state pointer */
114     S->pState = pState;
115 
116     status = ARM_MATH_SUCCESS;
117   }
118 
119   return (status);
120 
121 #else
122 
123   /* Assign filter taps */
124   S->numTaps = numTaps;
125 
126   /* Assign coefficient pointer */
127   S->pCoeffs = pCoeffs;
128 
129   /* Clear state buffer. The size is always (blockSize + numTaps - 1) */
130   memset(pState, 0, (numTaps + (blockSize - 1U)) * sizeof(q15_t));
131 
132   /* Assign state pointer */
133   S->pState = pState;
134 
135   status = ARM_MATH_SUCCESS;
136 
137   return (status);
138 
139 #endif /* #if defined (ARM_MATH_DSP) */
140 
141 }
142 
143 /**
144   @} end of FIR group
145  */
146