1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_q15_to_q7.c
4  * Description:  Converts the elements of the Q15 vector to Q7 vector
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/support_functions.h"
30 
31 /**
32   @ingroup groupSupport
33  */
34 
35 /**
36   @addtogroup q15_to_x
37   @{
38  */
39 
40 /**
41   @brief         Converts the elements of the Q15 vector to Q7 vector.
42   @param[in]     pSrc       points to the Q15 input vector
43   @param[out]    pDst       points to the Q7 output vector
44   @param[in]     blockSize  number of samples in each vector
45   @return        none
46 
47   @par           Details
48                    The equation used for the conversion process is:
49   <pre>
50       pDst[n] = (q7_t) pSrc[n] >> 8;   0 <= n < blockSize.
51   </pre>
52  */
53 #if defined(ARM_MATH_MVEI) && !defined(ARM_MATH_AUTOVECTORIZE)
arm_q15_to_q7(const q15_t * pSrc,q7_t * pDst,uint32_t blockSize)54 void arm_q15_to_q7(
55   const q15_t * pSrc,
56         q7_t * pDst,
57         uint32_t blockSize)
58 {
59 
60     uint32_t  blkCnt;           /* loop counters */
61     q15x8x2_t tmp;
62     q15_t const *pSrcVec;
63     q7x16_t vecDst = { 0 };
64 
65 
66     pSrcVec = (q15_t const *) pSrc;
67     blkCnt = blockSize >> 4;
68     while (blkCnt > 0U)
69     {
70         /* C = (q7_t) A >> 8 */
71         /* convert from q15 to q7 and then store the results in the destination buffer */
72         tmp = vld2q(pSrcVec);
73         pSrcVec += 16;
74         vecDst = vqshrnbq_n_s16(vecDst, tmp.val[0], 8);
75         vecDst = vqshrntq_n_s16(vecDst, tmp.val[1], 8);
76         vst1q(pDst, vecDst);
77         pDst += 16;
78         /*
79          * Decrement the blockSize loop counter
80          */
81         blkCnt--;
82     }
83 
84   blkCnt = blockSize & 0xF;
85   while (blkCnt > 0U)
86   {
87     /* C = (q7_t) A >> 8 */
88 
89     /* Convert from q15 to q7 and store result in destination buffer */
90     *pDst++ = (q7_t) (*pSrcVec++ >> 8);
91 
92     /* Decrement loop counter */
93     blkCnt--;
94   }
95 }
96 #else
arm_q15_to_q7(const q15_t * pSrc,q7_t * pDst,uint32_t blockSize)97 void arm_q15_to_q7(
98   const q15_t * pSrc,
99         q7_t * pDst,
100         uint32_t blockSize)
101 {
102         uint32_t blkCnt;                               /* Loop counter */
103   const q15_t *pIn = pSrc;                             /* Source pointer */
104 
105 #if defined (ARM_MATH_LOOPUNROLL) && defined (ARM_MATH_DSP)
106         q31_t in1, in2;
107         q31_t out1, out2;
108 #endif
109 
110 #if defined (ARM_MATH_LOOPUNROLL)
111 
112   /* Loop unrolling: Compute 4 outputs at a time */
113   blkCnt = blockSize >> 2U;
114 
115   while (blkCnt > 0U)
116   {
117     /* C = (q7_t) A >> 8 */
118 
119     /* Convert from q15 to q7 and store result in destination buffer */
120 #if defined (ARM_MATH_DSP)
121 
122     in1 = read_q15x2_ia ((q15_t **) &pIn);
123     in2 = read_q15x2_ia ((q15_t **) &pIn);
124 
125 #ifndef ARM_MATH_BIG_ENDIAN
126 
127     out1 = __PKHTB(in2, in1, 16);
128     out2 = __PKHBT(in2, in1, 16);
129 
130 #else
131 
132     out1 = __PKHTB(in1, in2, 16);
133     out2 = __PKHBT(in1, in2, 16);
134 
135 #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
136 
137     /* rotate packed value by 24 */
138     out2 = ((uint32_t) out2 << 8) | ((uint32_t) out2 >> 24);
139 
140     /* anding with 0xff00ff00 to get two 8 bit values */
141     out1 = out1 & 0xFF00FF00;
142     /* anding with 0x00ff00ff to get two 8 bit values */
143     out2 = out2 & 0x00FF00FF;
144 
145     /* oring two values(contains two 8 bit values) to get four packed 8 bit values */
146     out1 = out1 | out2;
147 
148     /* store 4 samples at a time to destiantion buffer */
149     write_q7x4_ia (&pDst, out1);
150 
151 #else
152 
153     *pDst++ = (q7_t) (*pIn++ >> 8);
154     *pDst++ = (q7_t) (*pIn++ >> 8);
155     *pDst++ = (q7_t) (*pIn++ >> 8);
156     *pDst++ = (q7_t) (*pIn++ >> 8);
157 
158 #endif /* #if defined (ARM_MATH_DSP) */
159 
160     /* Decrement loop counter */
161     blkCnt--;
162   }
163 
164   /* Loop unrolling: Compute remaining outputs */
165   blkCnt = blockSize % 0x4U;
166 
167 #else
168 
169   /* Initialize blkCnt with number of samples */
170   blkCnt = blockSize;
171 
172 #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
173 
174   while (blkCnt > 0U)
175   {
176     /* C = (q7_t) A >> 8 */
177 
178     /* Convert from q15 to q7 and store result in destination buffer */
179     *pDst++ = (q7_t) (*pIn++ >> 8);
180 
181     /* Decrement loop counter */
182     blkCnt--;
183   }
184 
185 }
186 #endif /* defined(ARM_MATH_MVEI) */
187 
188 /**
189   @} end of q15_to_x group
190  */
191