A bundled STM32F10x Std Periph and CMSIS library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

381 lines
11 KiB

  1. /* ----------------------------------------------------------------------
  2. * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
  3. *
  4. * $Date: 12. March 2014
  5. * $Revision: V1.4.4
  6. *
  7. * Project: CMSIS DSP Library
  8. * Title: arm_lms_q15.c
  9. *
  10. * Description: Processing function for the Q15 LMS filter.
  11. *
  12. * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions
  16. * are met:
  17. * - Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright
  20. * notice, this list of conditions and the following disclaimer in
  21. * the documentation and/or other materials provided with the
  22. * distribution.
  23. * - Neither the name of ARM LIMITED nor the names of its contributors
  24. * may be used to endorse or promote products derived from this
  25. * software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  35. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. * -------------------------------------------------------------------- */
  40. #include "arm_math.h"
  41. /**
  42. * @ingroup groupFilters
  43. */
  44. /**
  45. * @addtogroup LMS
  46. * @{
  47. */
  48. /**
  49. * @brief Processing function for Q15 LMS filter.
  50. * @param[in] *S points to an instance of the Q15 LMS filter structure.
  51. * @param[in] *pSrc points to the block of input data.
  52. * @param[in] *pRef points to the block of reference data.
  53. * @param[out] *pOut points to the block of output data.
  54. * @param[out] *pErr points to the block of error data.
  55. * @param[in] blockSize number of samples to process.
  56. * @return none.
  57. *
  58. * \par Scaling and Overflow Behavior:
  59. * The function is implemented using a 64-bit internal accumulator.
  60. * Both coefficients and state variables are represented in 1.15 format and multiplications yield a 2.30 result.
  61. * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format.
  62. * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved.
  63. * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits.
  64. * Lastly, the accumulator is saturated to yield a result in 1.15 format.
  65. *
  66. * \par
  67. * In this filter, filter coefficients are updated for each sample and the updation of filter cofficients are saturted.
  68. *
  69. */
  70. void arm_lms_q15(
  71. const arm_lms_instance_q15 * S,
  72. q15_t * pSrc,
  73. q15_t * pRef,
  74. q15_t * pOut,
  75. q15_t * pErr,
  76. uint32_t blockSize)
  77. {
  78. q15_t *pState = S->pState; /* State pointer */
  79. uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */
  80. q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */
  81. q15_t *pStateCurnt; /* Points to the current sample of the state */
  82. q15_t mu = S->mu; /* Adaptive factor */
  83. q15_t *px; /* Temporary pointer for state */
  84. q15_t *pb; /* Temporary pointer for coefficient buffer */
  85. uint32_t tapCnt, blkCnt; /* Loop counters */
  86. q63_t acc; /* Accumulator */
  87. q15_t e = 0; /* error of data sample */
  88. q15_t alpha; /* Intermediate constant for taps update */
  89. q31_t coef; /* Teporary variable for coefficient */
  90. q31_t acc_l, acc_h;
  91. int32_t lShift = (15 - (int32_t) S->postShift); /* Post shift */
  92. int32_t uShift = (32 - lShift);
  93. #ifndef ARM_MATH_CM0_FAMILY
  94. /* Run the below code for Cortex-M4 and Cortex-M3 */
  95. /* S->pState points to buffer which contains previous frame (numTaps - 1) samples */
  96. /* pStateCurnt points to the location where the new input data should be written */
  97. pStateCurnt = &(S->pState[(numTaps - 1u)]);
  98. /* Initializing blkCnt with blockSize */
  99. blkCnt = blockSize;
  100. while(blkCnt > 0u)
  101. {
  102. /* Copy the new input sample into the state buffer */
  103. *pStateCurnt++ = *pSrc++;
  104. /* Initialize state pointer */
  105. px = pState;
  106. /* Initialize coefficient pointer */
  107. pb = pCoeffs;
  108. /* Set the accumulator to zero */
  109. acc = 0;
  110. /* Loop unrolling. Process 4 taps at a time. */
  111. tapCnt = numTaps >> 2u;
  112. while(tapCnt > 0u)
  113. {
  114. /* acc += b[N] * x[n-N] + b[N-1] * x[n-N-1] */
  115. /* Perform the multiply-accumulate */
  116. #ifndef UNALIGNED_SUPPORT_DISABLE
  117. acc = __SMLALD(*__SIMD32(px)++, (*__SIMD32(pb)++), acc);
  118. acc = __SMLALD(*__SIMD32(px)++, (*__SIMD32(pb)++), acc);
  119. #else
  120. acc += (q63_t) (((q31_t) (*px++) * (*pb++)));
  121. acc += (q63_t) (((q31_t) (*px++) * (*pb++)));
  122. acc += (q63_t) (((q31_t) (*px++) * (*pb++)));
  123. acc += (q63_t) (((q31_t) (*px++) * (*pb++)));
  124. #endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */
  125. /* Decrement the loop counter */
  126. tapCnt--;
  127. }
  128. /* If the filter length is not a multiple of 4, compute the remaining filter taps */
  129. tapCnt = numTaps % 0x4u;
  130. while(tapCnt > 0u)
  131. {
  132. /* Perform the multiply-accumulate */
  133. acc += (q63_t) (((q31_t) (*px++) * (*pb++)));
  134. /* Decrement the loop counter */
  135. tapCnt--;
  136. }
  137. /* Calc lower part of acc */
  138. acc_l = acc & 0xffffffff;
  139. /* Calc upper part of acc */
  140. acc_h = (acc >> 32) & 0xffffffff;
  141. /* Apply shift for lower part of acc and upper part of acc */
  142. acc = (uint32_t) acc_l >> lShift | acc_h << uShift;
  143. /* Converting the result to 1.15 format and saturate the output */
  144. acc = __SSAT(acc, 16);
  145. /* Store the result from accumulator into the destination buffer. */
  146. *pOut++ = (q15_t) acc;
  147. /* Compute and store error */
  148. e = *pRef++ - (q15_t) acc;
  149. *pErr++ = (q15_t) e;
  150. /* Compute alpha i.e. intermediate constant for taps update */
  151. alpha = (q15_t) (((q31_t) e * (mu)) >> 15);
  152. /* Initialize state pointer */
  153. /* Advance state pointer by 1 for the next sample */
  154. px = pState++;
  155. /* Initialize coefficient pointer */
  156. pb = pCoeffs;
  157. /* Loop unrolling. Process 4 taps at a time. */
  158. tapCnt = numTaps >> 2u;
  159. /* Update filter coefficients */
  160. while(tapCnt > 0u)
  161. {
  162. coef = (q31_t) * pb + (((q31_t) alpha * (*px++)) >> 15);
  163. *pb++ = (q15_t) __SSAT((coef), 16);
  164. coef = (q31_t) * pb + (((q31_t) alpha * (*px++)) >> 15);
  165. *pb++ = (q15_t) __SSAT((coef), 16);
  166. coef = (q31_t) * pb + (((q31_t) alpha * (*px++)) >> 15);
  167. *pb++ = (q15_t) __SSAT((coef), 16);
  168. coef = (q31_t) * pb + (((q31_t) alpha * (*px++)) >> 15);
  169. *pb++ = (q15_t) __SSAT((coef), 16);
  170. /* Decrement the loop counter */
  171. tapCnt--;
  172. }
  173. /* If the filter length is not a multiple of 4, compute the remaining filter taps */
  174. tapCnt = numTaps % 0x4u;
  175. while(tapCnt > 0u)
  176. {
  177. /* Perform the multiply-accumulate */
  178. coef = (q31_t) * pb + (((q31_t) alpha * (*px++)) >> 15);
  179. *pb++ = (q15_t) __SSAT((coef), 16);
  180. /* Decrement the loop counter */
  181. tapCnt--;
  182. }
  183. /* Decrement the loop counter */
  184. blkCnt--;
  185. }
  186. /* Processing is complete. Now copy the last numTaps - 1 samples to the
  187. satrt of the state buffer. This prepares the state buffer for the
  188. next function call. */
  189. /* Points to the start of the pState buffer */
  190. pStateCurnt = S->pState;
  191. /* Calculation of count for copying integer writes */
  192. tapCnt = (numTaps - 1u) >> 2;
  193. while(tapCnt > 0u)
  194. {
  195. #ifndef UNALIGNED_SUPPORT_DISABLE
  196. *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++;
  197. *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++;
  198. #else
  199. *pStateCurnt++ = *pState++;
  200. *pStateCurnt++ = *pState++;
  201. *pStateCurnt++ = *pState++;
  202. *pStateCurnt++ = *pState++;
  203. #endif
  204. tapCnt--;
  205. }
  206. /* Calculation of count for remaining q15_t data */
  207. tapCnt = (numTaps - 1u) % 0x4u;
  208. /* copy data */
  209. while(tapCnt > 0u)
  210. {
  211. *pStateCurnt++ = *pState++;
  212. /* Decrement the loop counter */
  213. tapCnt--;
  214. }
  215. #else
  216. /* Run the below code for Cortex-M0 */
  217. /* S->pState points to buffer which contains previous frame (numTaps - 1) samples */
  218. /* pStateCurnt points to the location where the new input data should be written */
  219. pStateCurnt = &(S->pState[(numTaps - 1u)]);
  220. /* Loop over blockSize number of values */
  221. blkCnt = blockSize;
  222. while(blkCnt > 0u)
  223. {
  224. /* Copy the new input sample into the state buffer */
  225. *pStateCurnt++ = *pSrc++;
  226. /* Initialize pState pointer */
  227. px = pState;
  228. /* Initialize pCoeffs pointer */
  229. pb = pCoeffs;
  230. /* Set the accumulator to zero */
  231. acc = 0;
  232. /* Loop over numTaps number of values */
  233. tapCnt = numTaps;
  234. while(tapCnt > 0u)
  235. {
  236. /* Perform the multiply-accumulate */
  237. acc += (q63_t) ((q31_t) (*px++) * (*pb++));
  238. /* Decrement the loop counter */
  239. tapCnt--;
  240. }
  241. /* Calc lower part of acc */
  242. acc_l = acc & 0xffffffff;
  243. /* Calc upper part of acc */
  244. acc_h = (acc >> 32) & 0xffffffff;
  245. /* Apply shift for lower part of acc and upper part of acc */
  246. acc = (uint32_t) acc_l >> lShift | acc_h << uShift;
  247. /* Converting the result to 1.15 format and saturate the output */
  248. acc = __SSAT(acc, 16);
  249. /* Store the result from accumulator into the destination buffer. */
  250. *pOut++ = (q15_t) acc;
  251. /* Compute and store error */
  252. e = *pRef++ - (q15_t) acc;
  253. *pErr++ = (q15_t) e;
  254. /* Compute alpha i.e. intermediate constant for taps update */
  255. alpha = (q15_t) (((q31_t) e * (mu)) >> 15);
  256. /* Initialize pState pointer */
  257. /* Advance state pointer by 1 for the next sample */
  258. px = pState++;
  259. /* Initialize pCoeffs pointer */
  260. pb = pCoeffs;
  261. /* Loop over numTaps number of values */
  262. tapCnt = numTaps;
  263. while(tapCnt > 0u)
  264. {
  265. /* Perform the multiply-accumulate */
  266. coef = (q31_t) * pb + (((q31_t) alpha * (*px++)) >> 15);
  267. *pb++ = (q15_t) __SSAT((coef), 16);
  268. /* Decrement the loop counter */
  269. tapCnt--;
  270. }
  271. /* Decrement the loop counter */
  272. blkCnt--;
  273. }
  274. /* Processing is complete. Now copy the last numTaps - 1 samples to the
  275. start of the state buffer. This prepares the state buffer for the
  276. next function call. */
  277. /* Points to the start of the pState buffer */
  278. pStateCurnt = S->pState;
  279. /* Copy (numTaps - 1u) samples */
  280. tapCnt = (numTaps - 1u);
  281. /* Copy the data */
  282. while(tapCnt > 0u)
  283. {
  284. *pStateCurnt++ = *pState++;
  285. /* Decrement the loop counter */
  286. tapCnt--;
  287. }
  288. #endif /* #ifndef ARM_MATH_CM0_FAMILY */
  289. }
  290. /**
  291. * @} end of LMS group
  292. */