特别说明:完整45期数字信号处理教程,原创高性能示波器代码全开源地址:链接
! ?' k1 o3 ^1 [" j j1 E; h第9章 BasicMathFunctions的使用(二)
' F9 U: }$ o' a# A 本期教程主要讲基本函数中的相反数,偏移,位移,减法和比例因子。 9.1 相反数(Vector Negate) 9.2 求和(Vector Offset) 9.3 点乘(Vector Shift) 9.4 减法(Vector Sub) 9.5 比例因子(Vector Scale) 9.6 BasicMathFunctions的重要说明 9.7 总结
- d; V2 [, Y5 y' q9.1 相反数(Vector Negate) 这部分函数主要用于求相反数,公式描述如下: pDst[n] = -pSrc[n], 0 <= n < blockSize. 特别注意,这部分函数支持目标指针和源指针指向相同的缓冲区。 9.1.1 arm_negate_f32 这个函数用于求32位浮点数的相反数,源代码分析如下: - /** + c0 b! U* I! i3 {% p b
- * @brief Negates the elements of a floating-point vector.
6 d' C2 s( {/ d6 K' |" ^( M4 w - * @param[in] *pSrc points to the input vector . P4 d, D# V3 S- M& o, X
- * @param[out] *pDst points to the output vector : a/ V2 j2 k* E j" f
- * @param[in] blockSize number of samples in the vector 7 U% H" y. r; y/ A! s
- * @return none. 5 H; @8 \# I9 a% M. v. Z2 v
- */
: Q. b8 e1 i9 @6 M2 Q - l+ R! f; u. H7 n* `* t. `
- void arm_negate_f32(
; \5 c+ ]" F5 ^! Q1 R- d - float32_t * pSrc,, P2 i# I, L$ A; c1 [* E
- float32_t * pDst,$ x% u! h# S1 r$ ?# x! _$ a
- uint32_t blockSize); x/ B F1 R; M
- {
8 b" R R# N+ g0 }. Z' G' m - uint32_t blkCnt; /* loop counter */
$ X1 _; t1 x) U - / v+ M. s/ p" Z+ S$ G' {
- # x' B3 Y/ }% @1 n& q3 p
- #ifndef ARM_MATH_CM0_FAMILY
2 s% x; B4 ?/ a. r% B( w$ d9 Q -
% U, G L- p& [! p8 |/ y6 e - /* Run the below code for Cortex-M4 and Cortex-M3 */
' @, D. J5 V- z# ^; L$ v - float32_t in1, in2, in3, in4; /* temporary variables */6 b' q H* c1 L
-
, }2 M, q8 t, T/ H' M; o - /*loop Unrolling */0 h( t/ q- s. o& X! h. N N
- blkCnt = blockSize >> 2u;
3 J- Q" e9 C/ J' [' \& R" R -
+ N- l$ S& p; s3 X2 Z - /* First part of the processing with loop unrolling. Compute 4 outputs at a time. 7 c1 W7 {" @, c9 Q+ R5 v0 }( a3 W
- ** a second loop below computes the remaining 1 to 3 samples. */
6 L7 E2 }. O& B& P+ n - while(blkCnt > 0u)3 l/ J D" D- {, W \/ w; _6 B5 ]! M
- {
$ s" u$ I" A# ~( [+ F) N0 U - /* read inputs from source */$ q0 H4 W, e" M+ X- l/ s
- in1 = *pSrc;4 U! M/ w. f3 n# i5 d
- in2 = *(pSrc + 1);* x' B% x5 }& I2 |
- in3 = *(pSrc + 2);( S# ]+ i, Z z/ U: W' v8 i
- in4 = *(pSrc + 3);, W" r6 O8 S( Y2 O o
-
3 I5 W# R$ @6 `3 V4 F6 U& d - /* negate the input */ (1)6 u$ E9 W& K( {( j1 h; J& f
- in1 = -in1;+ H' g( D+ d4 b2 O% }
- in2 = -in2;
/ ?( c6 s% M5 O2 w$ V* {! e0 K% p - in3 = -in3;% f- z' e" b/ G, u4 J/ N
- in4 = -in4; v2 W v/ p9 Z# P' x. \
-
9 m5 X! ] D& ^* l) O7 S - /* store the result to destination */3 P0 {0 q/ w' y4 P* ]: r# q4 N
- *pDst = in1;
- ]9 V' w) m. E* d - *(pDst + 1) = in2;
% V# s5 m3 E- `" M! W5 J' |& \ - *(pDst + 2) = in3;3 V N7 y8 z/ m: K1 p' j- }
- *(pDst + 3) = in4;: ^( s( K$ G# N
-
3 s! M- z# w& E/ `5 x9 z+ f& I - /* update pointers to process next samples */
" [$ k5 v! D0 i/ L+ ^' Q - pSrc += 4u;
Y, ]7 [, z0 z z- o4 ?4 n) S; f - pDst += 4u;
% S3 M( U; x" R -
1 Y6 D5 u2 M' g - /* Decrement the loop counter */5 D6 ?0 ~" y/ i0 L: o# W
- blkCnt--;
+ }4 x @$ X5 Q; z - }
3 g' d3 L- Q$ v - ; O* j2 c3 g0 |3 o. I& V% r
- /* If the blockSize is not a multiple of 4, compute any remaining output samples here. 1 _# h: i3 F5 V+ c! s; r
- ** No loop unrolling is used. */: A0 i1 `1 c- N$ m* s) j
- blkCnt = blockSize % 0x4u;) x* m6 I- v) Y4 Y
-
7 g! P# G% M2 e - #else5 Y; X; {+ H1 P7 R) ?
- 9 ?3 t5 d# j1 _1 W6 s' Q7 ]
- /* Run the below code for Cortex-M0 */( I! s6 O0 l4 v5 Z+ Z7 T2 V7 u
- : l+ B4 T' v) @9 V
- /* Initialize blkCnt with number of samples */
0 Q; q) n* g$ Q. t& n" n - blkCnt = blockSize;; o. ]! B) ^" W
- 9 ]/ z& J+ D2 G" ^# ^* p# K M8 i
- #endif /* #ifndef ARM_MATH_CM0_FAMILY */+ @" t C7 c5 C, G; H+ E
- 6 z! q0 Z9 e* }) a( D- U8 X
- while(blkCnt > 0u) y8 g N' s( p8 o% }. c
- {
; q j- b% k' i6 J" v - /* C = -A */
; T N% F* m1 w# V8 t G - /* Negate and then store the results in the destination buffer. */6 B# O7 Y$ ?$ N1 ^0 M$ n
- *pDst++ = -*pSrc++;
6 d& q* `. K3 d4 T - 9 Q% p8 m+ R( m; n
- /* Decrement the loop counter */
; z5 M8 s* h5 z6 c5 ]* Q - blkCnt--;( n9 q. g% T9 n5 ~
- }# B' o0 l( c) D6 C/ e. f {- `
- }
复制代码1. 浮点数的相反数求解比较简单,直接在相应的变量前加上负号即可。
7 ^: Q6 j6 Y; @( H9.1.2 arm_negate_q31 这个函数用于求32位定点数的相反数,源代码分析如下: - /**
8 A* O0 e1 X x+ o3 \- f - * @brief Negates the elements of a Q31 vector.
% m% s1 O5 J3 e2 j" F - * @param[in] *pSrc points to the input vector
7 l: p3 j' S$ o - * @param[out] *pDst points to the output vector ! R$ Y' _! ?# r0 L" Q( E2 L
- * @param[in] blockSize number of samples in the vector ' N# e% o. i( @. w% R" \7 i
- * @return none. , N8 L- x1 o, d) s
- *
% N: ~2 c, O; l- m - * <b>Scaling and Overflow Behavior:</b> (1)
2 p+ T% X" P2 j. R) ]+ E9 a - * \par
6 |+ I$ h' e5 D) d3 r6 B1 w - * The function uses saturating arithmetic. , u) h" \2 @+ M, A: n
- * The Q31 value -1 (0x80000000) will be saturated to the maximum allowable positive value 0x7FFFFFFF.
- X$ X0 I+ C2 }0 u% Y2 }2 b6 Y - */# M" d" r3 u" \2 }
-
, z3 V/ |2 f- Z5 F/ i - void arm_negate_q31(
9 j( B( ]! I' y# p7 ?9 F - q31_t * pSrc,* I/ j: o2 |/ u2 d- g# T
- q31_t * pDst,
& U* N* m- U% C$ r$ A6 i - uint32_t blockSize)
/ a8 d/ {8 y8 K s* Z2 ?/ Z+ u# H( \ - {
- U3 R+ g; U8 ?5 W& G - q31_t in; /* Temporary variable */9 @/ A( p# n+ I0 y; e- g% H
- uint32_t blkCnt; /* loop counter */4 d: k, W% f2 ?
-
- F9 O# [6 E9 m6 H9 V, W - #ifndef ARM_MATH_CM0_FAMILY
0 I* @% s4 C t1 ` -
4 C, V2 p# [6 A+ n2 N - /* Run the below code for Cortex-M4 and Cortex-M3 */
9 n7 s/ w/ B! L& W& _, g& g- t( E - q31_t in1, in2, in3, in4;9 ?4 z8 I1 W, x+ q) e
-
8 k0 |0 e" N" J: M5 w a% U - /*loop Unrolling */
- M2 q6 s3 D7 O }# i" E0 k - blkCnt = blockSize >> 2u;% J: X3 \! q5 O* n& J, U
- 2 D0 I- P! L6 N' S- W0 W8 R& I
- /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
6 l3 g! |% F, F; d3 ~1 l - ** a second loop below computes the remaining 1 to 3 samples. */
8 ?& ?! @( |+ v% u5 v: Z - while(blkCnt > 0u)
* w+ q6 s. P) c0 [& p7 d - {
% S( r# W& }+ _ - /* C = -A */
- D- O% F, w3 y - /* Negate and then store the results in the destination buffer. */ e4 X0 E* w7 ]5 ?8 o1 e- ?
- in1 = *pSrc++;8 F; r; ~8 d* K/ o1 p5 F
- in2 = *pSrc++;
4 S( H' |; ~, A5 L2 h" m - in3 = *pSrc++; W+ _1 L$ P' w6 F5 ]; r; Y
- in4 = *pSrc++;" w9 j2 f! b/ t$ w3 u
-
8 f8 ]* l n4 I- W' n6 _7 T# a5 F m - *pDst++ = __QSUB(0, in1); (2)' ], A9 B; _8 u8 |
- *pDst++ = __QSUB(0, in2);
& V9 e- @/ n0 B# f1 ] - *pDst++ = __QSUB(0, in3);
- y- Z( B3 M# Q) K - *pDst++ = __QSUB(0, in4);
5 [( q0 [1 a! i2 t8 ^* Q - . \+ u: N% L( r4 l6 n! k
- /* Decrement the loop counter */
; T/ A! R. E3 i( w3 ]4 W, y% h - blkCnt--;# L/ m- D9 g! @( n! f I: G c# k. R
- }% Z* ?5 p# D% i9 Y( V
-
" r# E3 N# X) h& x1 [ - /* If the blockSize is not a multiple of 4, compute any remaining output samples here. ) @$ v' o; S, s' o" x
- ** No loop unrolling is used. */: m/ L* I0 I, {+ b% D; }
- blkCnt = blockSize % 0x4u;
/ n2 ]( r8 e: x -
: S( G- Y% {8 w# S3 Y& q0 U - #else
+ d, J+ s# h" D6 k" ?4 o -
. W- F1 D% D3 z, W - /* Run the below code for Cortex-M0 */% e( L4 s4 I1 k$ T) M
- / _- V4 l3 w! p) s3 m1 T. R
- /* Initialize blkCnt with number of samples */) n. ?; j6 g; }& O* |! f! \" x
- blkCnt = blockSize;
a" \3 v4 ?, z- m! p0 d -
3 Q( Y1 L' D6 j - #endif /* #ifndef ARM_MATH_CM0_FAMILY */
+ o' {* v3 ^) b - 1 \) |) H6 I; I6 X
- & Z0 R2 y) e& E, [% |
- while(blkCnt > 0u)
' [) f0 h8 d6 ~) Y6 @ - {
/ x' y5 F8 w s' ?# a% h3 [. h - /* C = -A */
5 r) F7 W. z4 A Q' h# | - /* Negate and then store the result in the destination buffer. */
' c& p5 G5 \& ^/ g0 u, J - in = *pSrc++;9 a y. D6 x% N7 _
- *pDst++ = (in == INT32_MIN) ? INT32_MAX : -in;) r3 U+ V) Q' v# q @
- 6 o0 k$ t2 U. L- v4 G+ t
- /* Decrement the loop counter */
/ ?3 [+ S( U* `6 R4 \$ b - blkCnt--;) G% L; a4 g) l% w9 v/ O: ~3 D
- }% k" q6 }+ k! E7 l
- }
复制代码1. 这个函数使用了饱和运算。 饱和运算数值0x80000000将变成0x7FFFFFFF。 2. 饱和运算__QSUB我们在上一章已经详细讲述了,这就就是实现数值0减去相应的参数变量。
2 C. |& j( [$ j/ N# B9 R& h. K9.1.3 arm_negate_q15 这个函数用于求16位定点数的相反数,源代码分析如下: - /**
1 [+ u! k) G4 M2 ^, j& W - * @brief Negates the elements of a Q15 vector. - \; d5 c& r2 b
- * @param[in] *pSrc points to the input vector . a7 G/ {6 \7 A+ x6 G
- * @param[out] *pDst points to the output vector 7 @. z$ R0 K# c9 G. C9 c |
- * @param[in] blockSize number of samples in the vector , i& @8 }7 k0 d* |* N8 U
- * @return none. ) d7 G2 }5 |' I4 U; }
- * - m, V* \2 n1 A; v+ W0 z
- * \par Conditions for optimum performance 1 M9 z$ b) x) r: [0 G" |& }
- * Input and output buffers should be aligned by 32-bit
- J. z) s+ y+ w2 c9 E4 ] - *
# Y- C, c/ d i - * 9 ^- ~8 k+ i$ ~8 h) F( r4 e
- * <b>Scaling and Overflow Behavior:</b> (1)( C) ?1 D( r0 f h
- * \par ( ~- x1 Y3 ^5 c
- * The function uses saturating arithmetic.
9 c* h" m% g. U/ Q7 W' e( G3 S - * The Q15 value -1 (0x8000) will be saturated to the maximum allowable positive value 0x7FFF.
1 L7 {5 z# q- Q9 V) h0 a1 m - */
9 N Z C. D9 @2 l, l -
1 |+ f. {9 |; d0 {6 G( a - void arm_negate_q15(' U( r: N& R+ @ a- O1 i+ _5 U* M
- q15_t * pSrc,
* r- Q4 k, E. O M0 h( ? - q15_t * pDst,; G" W4 f) M6 f2 a" [ r* [- k- F
- uint32_t blockSize)
( ^8 c* X5 ~6 b - {* h3 b2 z/ W, F3 G; x. F( S" P I- y
- uint32_t blkCnt; /* loop counter */( K2 ]8 [- W( f; X2 }: A# S
- q15_t in;7 V, H7 Z- o; s) ?2 C# l( S1 z
- / D$ I7 C9 ]& f9 d+ p) m6 D
- #ifndef ARM_MATH_CM0_FAMILY8 W# M- d" T. d0 a8 T" v
- - v) b- }) T, F4 |$ i
- /* Run the below code for Cortex-M4 and Cortex-M3 */( F6 v1 n2 m; h$ ^
-
4 C+ n, @- B2 L+ a* j - q31_t in1, in2; /* Temporary variables */
}/ h3 V7 y X( Y -
' w( d" X* |% u2 X# O3 K -
6 |& I8 x7 d2 Q, u7 f; v - /*loop Unrolling */
: `+ h, L# J8 I8 m! R, A( m" } - blkCnt = blockSize >> 2u;: D' r" i9 @' [/ u* X
-
3 z4 m V3 M) b1 o2 X; W, @ - /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
" p2 m2 R" q1 m, v - ** a second loop below computes the remaining 1 to 3 samples. */
6 }2 m2 I+ c0 [+ C p7 f9 F - while(blkCnt > 0u)
6 \6 J% ~" E$ Y( w$ Y' I" S" q - {0 w/ e- P: x/ Y
- /* C = -A *// ~1 i8 n* h6 N& A6 W# W
- /* Read two inputs at a time */ (2)' |% t. x. N, J
- in1 = _SIMD32_OFFSET(pSrc);) P# W, s$ E2 e+ C9 A# `
- in2 = _SIMD32_OFFSET(pSrc + 2);! Z7 b% u$ p+ R; v
-
4 {) C5 h3 O8 y( g8 v b) L - /* negate two samples at a time */ (3)
9 o+ X* i: Q& _ ~1 b6 C - in1 = __QSUB16(0, in1);
7 b6 c! T+ R7 c/ H) ]8 f -
% v' ]& Z& H0 c! L - /* negate two samples at a time */
6 D t1 | k+ |* E - in2 = __QSUB16(0, in2);/ ?' h- K$ m7 q( p8 p
- 3 C8 d$ R, j9 L/ L- O
- /* store the result to destination 2 samples at a time */ (4)! l q. F1 ?7 M/ f; Z# H- U
- _SIMD32_OFFSET(pDst) = in1;
9 [1 e- F$ c: v) c2 `/ k2 V - /* store the result to destination 2 samples at a time */! A$ S, V. z# b8 f* [2 |4 ^, V+ l
- _SIMD32_OFFSET(pDst + 2) = in2;9 s% ^6 U) }# j, f
- 0 [7 X$ z; |: i9 A
-
; T5 \$ {( C& d3 K( w L - /* update pointers to process next samples */
7 m9 Z! ^3 @0 k - pSrc += 4u;
; p/ ?: I0 _2 V* I - pDst += 4u;& x: h. |6 o3 Y
- 4 E5 W% H; F1 Q9 N; Y
- /* Decrement the loop counter */) j& i! _- N' J- h% c1 D9 S
- blkCnt--;# L% g/ J7 r# u* W3 b6 ~5 l
- }5 Z( E0 F Z- r) k
- $ O: b% B% l" P6 W
- /* If the blockSize is not a multiple of 4, compute any remaining output samples here. % Q# j8 m! f0 C! b6 x* a
- ** No loop unrolling is used. */. C# S- `- l/ f# p8 w! ?3 ^
- blkCnt = blockSize % 0x4u;. o; ^2 x. J+ L& E# [4 i% `; `
- 6 b% E/ G. J' a0 n6 ?$ ]6 F
- #else
* P8 u6 z9 ]. f$ e' I* B0 b - z3 Y- {" a, ^: T4 {1 s+ U
- /* Run the below code for Cortex-M0 */
2 W- x! n/ S! D1 [4 r -
5 N3 h' f p7 C+ g - /* Initialize blkCnt with number of samples */2 t! k% X- Z4 g7 F
- blkCnt = blockSize;" h( `+ i W% y- z, N5 _6 x
-
% H! Y+ ?( W2 z$ Z! F/ ^8 G - #endif /* #ifndef ARM_MATH_CM0_FAMILY */" e- O' Q2 E0 B3 a$ Q, F8 F
- * y/ Z8 w- P6 F7 S3 y' J
- while(blkCnt > 0u)- R' A4 \) b! z9 h
- {
- x, R6 [% h; M0 @* v; C, b& [$ | - /* C = -A */% S) v" Q4 e( [" {5 H. k
- /* Negate and then store the result in the destination buffer. */; I. U5 c1 d: ]/ f) d
- in = *pSrc++;5 z: x- S, R7 q7 z3 ?0 C* \
- *pDst++ = (in == (q15_t) 0x8000) ? 0x7fff : -in; f$ {3 g R4 l! g$ w1 c% M' j! K
-
' L- J( A5 [+ T) w; J( P - /* Decrement the loop counter */
# N3 L# D0 f: y4 M7 o# U& R, Q, F0 O - blkCnt--;% V% A$ E9 s- ]2 V* g
- }
" I9 x* |8 c1 E% Q7 h - }
复制代码1. 这个函数使用了饱和运算。 饱和运算数值0x8000将变成0x7FFF。 2. 一次读取两个Q15格式的数据。 3. 由于__QSUB是SIMD指令,这里可以实现一次计算两个Q15数据的相反数。 4. 这里实现一次赋值两个Q15数据。
& D$ X1 A2 S- c8 z. p) z% A9.1.4 arm_negate_q7 这个函数用于求8位定点数的相反数,源代码分析如下: - /**
7 Q( {: r- L3 e" j% z d - * @brief Negates the elements of a Q7 vector. # c- |4 d3 V4 Q$ |1 J
- * @param[in] *pSrc points to the input vector / N& q% n( N0 }+ m
- * @param[out] *pDst points to the output vector - C; g# G& ?# a6 D
- * @param[in] blockSize number of samples in the vector
& I( x3 l( G3 D, b% q' Y - * @return none. 2 j- @) ?) W1 D; ]" R5 R6 P
- *
' ]( O; F4 u H; \( S$ d2 M* \ - * <b>Scaling and Overflow Behavior:</b> (1)
8 ]" _# q6 X# X - * \par 4 ^6 N2 F8 M. ^2 _, \
- * The function uses saturating arithmetic.
8 J! {: n: P4 a' X! F v - * The Q7 value -1 (0x80) will be saturated to the maximum allowable positive value 0x7F. $ G! p% w; B) u( k) s5 M }
- */3 K4 r; u! I4 C8 ^2 f% e3 z5 V9 I5 e
- % O5 a; I& U: V, g4 o! p, q, d
- void arm_negate_q7( h x, }2 E7 a1 k5 f0 t% F! y% `
- q7_t * pSrc,0 N1 F0 ~- x+ ?$ V
- q7_t * pDst,7 D8 B1 p4 B: w' [ _
- uint32_t blockSize)) V C# w* {7 ^& _( B5 b' @
- {( {2 p/ D7 _. Z( B% ^8 K
- uint32_t blkCnt; /* loop counter */! z# p4 t" Y. ]) ~
- q7_t in;
7 P: I; B0 L. e6 U; O) B( I - ( t/ V! S3 O: S: z" ]9 W* n
- #ifndef ARM_MATH_CM0_FAMILY
* C# _) Y/ Z0 N! J - % \! E$ d% o; p9 L# d; _
- /* Run the below code for Cortex-M4 and Cortex-M3 */) ]! Q \* J! O/ s
- q31_t input; /* Input values1-4 */$ Y) C, I! I t' e+ Z- L
- q31_t zero = 0x00000000; (2)
; G$ C! x* t; U {) C& v0 a [ - 3 A$ p; j: h- Y; q+ g8 n. q
- 0 N0 X& z* M5 D2 D. x) W5 ?8 ? o/ ~
- /*loop Unrolling */
: C" F {' p+ W - blkCnt = blockSize >> 2u;( |# F L% a* Y% [" A
- 6 E; X2 A8 d0 F$ C9 {3 T
- /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
) Z/ ^* M- M9 t% h) Y6 \' e$ ^# b - ** a second loop below computes the remaining 1 to 3 samples. */7 g, [2 y% X) ~: l3 |. ^6 |
- while(blkCnt > 0u)
8 y3 ?) w& c) J1 r - {% s' l$ T9 g. ^2 L
- /* C = -A */
( Q. ]( H( w4 J$ n3 X5 q2 B - /* Read four inputs */
* a; ]5 O3 C7 P+ L4 }1 I - input = *__SIMD32(pSrc)++; (3) T: b# d- b: l/ w1 `, b, [
-
$ Q" V1 C! s: G6 F9 }6 j - /* Store the Negated results in the destination buffer in a single cycle by packing the results */
! {6 R- i7 I; O8 i - *__SIMD32(pDst)++ = __QSUB8(zero, input); (4)/ [) V5 c6 @$ t; X8 [
-
/ A Q" T$ o/ a& ~; X8 _1 c4 g - /* Decrement the loop counter */4 u) O* g0 L: ?& d8 q5 n+ n% H" s/ p
- blkCnt--;" h1 v8 T* R1 R
- }
# d5 ]2 p @- k+ ]6 r; g: P7 q0 P( z/ N -
0 R) s, V/ D" u# @. k: i, s - /* If the blockSize is not a multiple of 4, compute any remaining output samples here. ( Y( n9 e" E3 K! ?% l6 _
- ** No loop unrolling is used. */
( f6 P2 a. r! ^+ a6 B - blkCnt = blockSize % 0x4u;
# c3 u/ y% W9 K3 l2 B -
2 k% v! m6 l) b2 o: c - #else" X% l; Z7 ~( A$ S u0 W
-
+ ^8 X" P1 b2 R P - /* Run the below code for Cortex-M0 */: P/ ]7 N3 I/ v7 K1 l8 L
-
% T$ h$ t& J1 V8 b' ^ - /* Initialize blkCnt with number of samples */
: U0 l( j4 O' M7 i! d) X% g8 u' Y W - blkCnt = blockSize;+ l) u; V. L1 {7 M- c' z/ C
- # y/ R* C( x$ b
- #endif /* #ifndef ARM_MATH_CM0_FAMILY */
) f) o1 b0 r/ b8 P0 O% E# | -
3 Q* e k$ C% r- a3 g9 c2 Y( J3 p5 I - while(blkCnt > 0u)9 b( H: T3 \! F( M
- {
! J+ h5 g# i J5 B- c - /* C = -A */
% F9 d0 O4 C. X) t: m7 d2 c - /* Negate and then store the results in the destination buffer. */ \
+ u) o4 V/ `/ n% c1 {4 ?- U9 e8 {9 x - in = *pSrc++;1 W0 m4 I& ~5 I: A" m
- *pDst++ = (in == (q7_t) 0x80) ? 0x7f : -in;4 F7 ` D$ W# U: e* b9 G
-
: n# C" i9 C/ ~& f2 a% b% N; r% U - /* Decrement the loop counter */
, e) `4 t$ I, U9 r - blkCnt--;
" {1 U& g7 _: r+ k; _; f - }
. \; i. S2 H8 v - }
复制代码1. 这个函数使用了饱和运算。 饱和运算数值0x80将变成0x7F。 2. 给局部变量赋初值,防止默认初始值不是0,所以从某种意义上来说,给变量赋初值是很有必要的。 3. 一次读取4个Q7格式的数据到input里面。 4. 通过__QSUB8实现一次计算四个Q7格式数据的相反数。
& V- i6 x+ E' M- M9.1.5 实例讲解实验目的: 1. 四种类型数据的相反数。 实验内容: 1. 按下K1键, 串口打印输出结果 实验现象: 通过窗口上位机软件SecureCRT(V5光盘里面有此软件)查看打印信息现象如下: 程序设计: - /*
3 x& z0 c% ?" ` - *********************************************************************************************************8 `" h4 e. t; `
- * 函 数 名: DSP_Negate# s0 _- L) @5 g- U) }+ }/ L2 e0 b
- * 功能说明: 求相反数5 ~/ W; g( N! m/ B
- * 形 参:无9 M* p( w- R4 G: U+ g% L6 n4 B
- * 返 回 值: 无
2 W$ Q m# b! p) C, G - *********************************************************************************************************/ ] R- v6 u( E( p5 \) y0 j, @0 s
- */# C# M4 b$ L( V$ g! I6 A8 s
- static void DSP_Negate(void)
1 k+ `8 P L# {3 P/ \& d. P7 T - {
0 S8 e2 k& k7 a1 s5 B - static float32_t pSrc;
9 l! K$ a$ P0 A% \ - static float32_t pDst;9 G- V1 ?- {) y0 h9 s. m1 c
- static q31_t pSrc1;
, A& h5 a: O8 V( L+ l% B4 ] - static q31_t pDst1;
. l1 ~( j( Y2 O6 x - static q15_t pSrc2;) l2 `/ ]* a* ~! q* D% n! S
- static q15_t pDst2;
1 X1 d7 A z Q7 q4 V - static q7_t pSrc3 = 127; /* 为了说明问题,在这里设置初始值为127,然后查看0x80是否饱和为0x7F */
# X: C. `' G: j0 |3 C6 I - static q7_t pDst3;& y5 S0 V# o( C+ ^8 i1 o: ]" }
- pSrc -= 1.23f;) ~7 ~% B) R. L2 E: y( h
- arm_negate_f32(&pSrc, &pDst, 1);
, {# U3 S( f- p8 u& }* |& P - printf("arm_negate_f32 = %f\r\n", pDst);! p% q3 Q' l( F @
-
% F; a" O+ ?+ H7 ~; B, w$ n: u - pSrc1 -= 1;
" G9 z, } E* v) \4 C3 ~ - arm_negate_q31(&pSrc1, &pDst1, 1);) N( ~8 P$ ]9 n5 S, P8 X4 w3 e
- printf("arm_negate_q31 = %d\r\n", pDst1);
6 D: H! S6 d: a. f6 a - V( |8 B8 v/ w- B$ W
- pSrc2 -= 1;# x0 q9 Y% M$ C* g4 `
- arm_negate_q15(&pSrc2, &pDst2, 1);
, ^/ A; k* S$ c8 l - printf("arm_negate_q15 = %d\r\n", pDst2);
9 g, N+ J3 @) Y8 C% G -
% z. s( p4 m4 H& N v. g - pSrc3 += 1;
. r, z& H7 l; j - arm_negate_q7(&pSrc3, &pDst3, 1);* P y" E9 D% C& |6 a" R
- printf("arm_negate_q7 = %d\r\n", pDst3);
B3 b' o& V( v) Z* p) p - printf("***********************************\r\n");
+ \; E# ?' P1 J1 e/ ^ - }
复制代码 - D6 ?9 S4 k* G; T5 n% G% f7 E0 H
|
9.2.2 arm_offset_q31
9.2.3 arm_offset_q15
9.2.4 arm_offset_q7
9.2.5 实例讲解
9.3.2 arm_shift_q15
) v5 `' A/ Y: o) C6 W, Q( B
9.3.4 实例讲解
9.4.2 arm_sub_q31
9.4.3 arm_sub_q15
9.4.4 arm_sub_q7
9.4.5 实例讲解
9.5.2 arm_scale_q31
9.5.3 arm_scale_q15
2 C2 O2 f5 H( ~
9.5.5 实例讲解
9.7 总结