1
2 /**
3 * @file xmc_math.c
4 * @date 2018-08-08
5 *
6 * @cond
7 **********************************************************************************
8 * XMClib v2.1.24 - XMC Peripheral Driver Library
9 *
10 * Copyright (c) 2015-2019, Infineon Technologies AG
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification,are permitted provided that the following conditions are met:
15 *
16 * Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 *
19 * Redistributions in binary form must reproduce the above copyright notice,
20 * this list of conditions and the following disclaimer in the documentation
21 * and/or other materials provided with the distribution.
22 *
23 * Neither the name of the copyright holders nor the names of its contributors
24 * may be used to endorse or promote products derived from this software without
25 * specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 *
39 * To improve the quality of the software, users are encouraged to share
40 * modifications, enhancements or bug fixes with Infineon Technologies AG
41 * dave@infineon.com).
42 **********************************************************************************
43 *
44 * Change History
45 * --------------
46 *
47 * 2015-06-20:
48 * - Removed version macros and declaration of GetDriverVersion API <br>
49 * - Updated copyright and change history section.
50 *
51 * 2015-09-23:
52 * - Added SQRT functions
53 *
54 * 2015-10-08:
55 * - Return values for sin(), cos(), sinh(), cosh(), arctan() are corrected.
56 *
57 * 2017-04-20:
58 * - Foward declaration of __aeabi_* to fix link time optimization (-flto) compilation errors
59 *
60 * 2017-11-30:
61 * - Fixed reentrancy problems when using __aeabi_* functions (division ‘/’ and modulo ‘%’ C operators) which are active by default
62 * as long as XMC_MATH_DISABLE_DIV_ABI is not defined
63 *
64 * 2018-08-08:
65 * - Fixed compiler warnings for compiler others than GCC
66 *
67 * @endcond
68 *
69 */
70
71 /**
72 *
73 * @brief MATH driver - API implementation for XMC13/14 family MATH libraries. <br>
74 *
75 * <b>Detailed description of file</b> <br>
76 * APIs provided in this file cover the following functional blocks of MATH: <br>
77 *
78 */
79
80 /*********************************************************************************************************************
81 * HEADER FILES
82 ********************************************************************************************************************/
83 #include <xmc_math.h>
84
85 #if defined (MATH)
86 /*********************************************************************************************************************
87 * MACROS
88 ********************************************************************************************************************/
89 /* Reciprocal of Circular gain in XMC_MATH_Q0_23_t format ((2^23)/1.646760258121) */
90 #define XMC_MATH_RECIPROC_CIRCULAR_GAIN_IN_Q023 (0x4DBA76U)
91 /* Reciprocal of Hyperbolic gain in XMC_MATH_Q1_22_t format ((2^22)/0.828159360960) */
92 #define XMC_MATH_RECIPROC_HYPERBOLIC_GAIN_IN_Q1_22 (0x4D47A1U)
93 /* Signed division is selected */
94 #define XMC_MATH_SIGNED_DIVISION ((uint32_t) 0 << MATH_DIVCON_USIGN_Pos)
95 /* Unsigned division is selected */
96 #define XMC_MATH_UNSIGNED_DIVISION ((uint32_t) 1 << MATH_DIVCON_USIGN_Pos)
97
98 /*********************************************************************************************************************
99 * ENUMS
100 ********************************************************************************************************************/
101
102 /*********************************************************************************************************************
103 * GLOBAL DATA
104 ********************************************************************************************************************/
105
106 /*********************************************************************************************************************
107 * DATA STRUCTURES
108 ********************************************************************************************************************/
109
110 /*********************************************************************************************************************
111 * LOCAL ROUTINES
112 ********************************************************************************************************************/
113
114 /*********************************************************************************************************************
115 * API IMPLEMENTATION - Utility functions
116 ********************************************************************************************************************/
critical_section_enter(void)117 __attribute__((always_inline)) __STATIC_INLINE uint32_t critical_section_enter(void)
118 {
119 uint32_t status;
120 status = __get_PRIMASK();
121 __disable_irq ();
122 return status;
123 }
124
critical_section_exit(uint32_t status)125 __attribute__((always_inline)) __STATIC_INLINE void critical_section_exit(uint32_t status)
126 {
127 __set_PRIMASK(status);
128 }
129
130 /* Utility function to check if the DIV unit is busy */
XMC_MATH_DIV_IsBusy(void)131 bool XMC_MATH_DIV_IsBusy(void)
132 {
133 bool status;
134 if (MATH->DIVST & MATH_DIVST_BSY_Msk)
135 {
136 status = true; /* DIV unit is busy running a division operation */
137 }
138 else
139 {
140 status = false; /* DIV unit is idle */
141 }
142
143 return (status);
144 }
145
146 /* Utility function to check if the CORDIC unit is busy */
XMC_MATH_CORDIC_IsBusy(void)147 bool XMC_MATH_CORDIC_IsBusy(void)
148 {
149 bool status;
150 if (MATH->STATC & MATH_STATC_BSY_Msk)
151 {
152 status = true; /* CORDIC unit is busy running an operation */
153 }
154 else
155 {
156 status = false; /* CORDIC unit is idle */
157 }
158
159 return (status);
160 }
161
162 /* This functions returns the status of a requested event */
XMC_MATH_GetEventStatus(const XMC_MATH_EVENT_t event)163 bool XMC_MATH_GetEventStatus(const XMC_MATH_EVENT_t event)
164 {
165 bool status;
166 if (MATH->EVFR & (uint32_t) event)
167 {
168 status = true; /* Requested event has been detected */
169 }
170 else
171 {
172 status = false; /* Requested event has not been detected */
173 }
174 return (status);
175 }
176
177 #ifndef XMC_MATH_DISABLE_DIV_ABI
178
179 /* Forward prototypes. */
180 #if defined ( __GNUC__ )
181 uint32_t __aeabi_uidiv(uint32_t dividend, uint32_t divisor) __attribute__((externally_visible));
182 int32_t __aeabi_idiv(int32_t dividend, int32_t divisor) __attribute__((externally_visible));
183 uint64_t __aeabi_uidivmod(uint32_t dividend, uint32_t divisor) __attribute__((externally_visible));
184 int64_t __aeabi_idivmod(int32_t dividend, int32_t divisor) __attribute__((externally_visible));
185 #else
186 uint32_t __aeabi_uidiv(uint32_t dividend, uint32_t divisor);
187 int32_t __aeabi_idiv(int32_t dividend, int32_t divisor);
188 uint64_t __aeabi_uidivmod(uint32_t dividend, uint32_t divisor);
189 int64_t __aeabi_idivmod(int32_t dividend, int32_t divisor);
190 #endif
191
192 /***********************************************************************************************************************
193 * API IMPLEMENTATION - aeabi routines
194 **********************************************************************************************************************/
195 /* This function performs unsigned integer division */
__aeabi_uidiv(uint32_t dividend,uint32_t divisor)196 uint32_t __aeabi_uidiv(uint32_t dividend, uint32_t divisor)
197 {
198 uint32_t result;
199 uint32_t ics;
200 ics = critical_section_enter();
201
202 MATH->DIVCON = XMC_MATH_UNSIGNED_DIVISION;
203 MATH->DVD = dividend;
204 MATH->DVS = divisor;
205
206 result = MATH->QUOT;
207
208 critical_section_exit(ics);
209
210 return result;
211 }
212
213 /* This function performs signed integer division */
__aeabi_idiv(int32_t dividend,int32_t divisor)214 int32_t __aeabi_idiv(int32_t dividend, int32_t divisor)
215 {
216 uint32_t result;
217 uint32_t ics;
218 ics = critical_section_enter();
219
220 MATH->DIVCON = XMC_MATH_SIGNED_DIVISION;
221 MATH->DVD = dividend;
222 MATH->DVS = divisor;
223
224 result = MATH->QUOT;
225
226 critical_section_exit(ics);
227
228 return result;
229 }
230
231 /* This function performs unsigned integer division modulo */
__aeabi_uidivmod(uint32_t dividend,uint32_t divisor)232 uint64_t __aeabi_uidivmod(uint32_t dividend, uint32_t divisor)
233 {
234 uint64_t remainder;
235 uint64_t quot;
236 uint32_t ics;
237 ics = critical_section_enter();
238
239 MATH->DIVCON = XMC_MATH_UNSIGNED_DIVISION;
240 MATH->DVD = dividend;
241 MATH->DVS = divisor;
242
243 remainder = (uint64_t)MATH->RMD;
244 quot = (uint64_t)MATH->QUOT;
245
246 critical_section_exit(ics);
247
248 return ((remainder << 32) | quot);
249 }
250
251 /* This function performs signed integer division modulo */
__aeabi_idivmod(int32_t dividend,int32_t divisor)252 int64_t __aeabi_idivmod(int32_t dividend, int32_t divisor)
253 {
254 uint64_t remainder;
255 uint64_t quot;
256 uint32_t ics;
257 ics = critical_section_enter();
258
259 MATH->DIVCON = XMC_MATH_SIGNED_DIVISION;
260 MATH->DVD = dividend;
261 MATH->DVS = divisor;
262
263 remainder = (uint64_t)MATH->RMD;;
264 quot = (uint64_t)MATH->QUOT;
265
266 critical_section_exit(ics);
267
268 return ((int64_t)((remainder << 32) | quot));
269 }
270 #endif
271
272 /***********************************************************************************************************************
273 * API IMPLEMENTATION - Blocking functions
274 **********************************************************************************************************************/
275 /* This function computes the cosine of a given angle in radians */
XMC_MATH_CORDIC_Cos(XMC_MATH_Q0_23_t angle_in_radians)276 XMC_MATH_Q0_23_t XMC_MATH_CORDIC_Cos(XMC_MATH_Q0_23_t angle_in_radians)
277 {
278 int32_t result;
279 MATH->STATC = 0U; /* Clear register */
280 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_CIRCULAR + \
281 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
282 MATH->CORDZ = ((uint32_t) angle_in_radians) << MATH_CORDZ_DATA_Pos;
283 MATH->CORDY = 0U; /* Clear register */
284 MATH->CORDX = XMC_MATH_RECIPROC_CIRCULAR_GAIN_IN_Q023 << MATH_CORDX_DATA_Pos;
285 result = ((int32_t)MATH->CORRX) >> MATH_CORRX_RESULT_Pos;
286 return ((XMC_MATH_Q0_23_t) result);
287 }
288
289 /* This function computes the sine of a given angle in radians */
XMC_MATH_CORDIC_Sin(XMC_MATH_Q0_23_t angle_in_radians)290 XMC_MATH_Q0_23_t XMC_MATH_CORDIC_Sin(XMC_MATH_Q0_23_t angle_in_radians)
291 {
292 int32_t result;
293 MATH->STATC = 0U; /* Clear register */
294 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_CIRCULAR + \
295 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
296 MATH->CORDZ = ((uint32_t)angle_in_radians) << MATH_CORDZ_DATA_Pos;
297 MATH->CORDY = 0U; /* Clear register */
298 MATH->CORDX = XMC_MATH_RECIPROC_CIRCULAR_GAIN_IN_Q023 << MATH_CORDX_DATA_Pos;
299 result = ((int32_t)MATH->CORRY) >> MATH_CORRY_RESULT_Pos;
300 return ((XMC_MATH_Q0_23_t) result);
301 }
302
303 /* This function computes the tangent of a given angle in radians */
XMC_MATH_CORDIC_Tan(XMC_MATH_Q0_23_t angle_in_radians)304 XMC_MATH_Q0_11_t XMC_MATH_CORDIC_Tan(XMC_MATH_Q0_23_t angle_in_radians)
305 {
306 uint32_t result;
307 MATH->GLBCON = (uint32_t) XMC_MATH_DIV_DVDRC_CORRY_IS_SOURCE + \
308 (uint32_t) XMC_MATH_DIV_DVSRC_CORRX_IS_SOURCE; /* Chain the results of CORDIC operation to DIV unit */
309 MATH->DIVCON = (uint32_t) 11 << MATH_DIVCON_DVSSRC_Pos; /* Right Shifts Divisor by 11 places prior to division */
310 MATH->STATC = 0U; /* Clear register */
311 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_CIRCULAR + \
312 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
313 MATH->CORDZ = ((uint32_t)angle_in_radians) << MATH_CORDZ_DATA_Pos;
314 MATH->CORDY = 0U; /* Clear register */
315 MATH->CORDX = XMC_MATH_RECIPROC_CIRCULAR_GAIN_IN_Q023 << MATH_CORDX_DATA_Pos;
316 result = MATH->QUOT;
317 return ((XMC_MATH_Q0_11_t) result);
318 }
319
320 /* This function computes the arc tangent of a given angle in radians */
XMC_MATH_CORDIC_ArcTan(XMC_MATH_Q8_15_t x,XMC_MATH_Q8_15_t y)321 XMC_MATH_Q0_23_t XMC_MATH_CORDIC_ArcTan(XMC_MATH_Q8_15_t x, XMC_MATH_Q8_15_t y)
322 {
323 uint32_t result;
324 MATH->STATC = 0U; /* Clear register */
325 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_CIRCULAR;
326 MATH->CORDZ = 0U; /* Clear register */
327 MATH->CORDY = ((uint32_t) y) << MATH_CORDY_DATA_Pos;
328 MATH->CORDX = ((uint32_t) x) << MATH_CORDX_DATA_Pos;
329 result = ((int32_t)MATH->CORRZ) >> MATH_CORRZ_RESULT_Pos;
330 return ((XMC_MATH_Q0_23_t) result);
331 }
332
333 /* This function computes the hyperbolic cosine of a given angle in radians */
XMC_MATH_CORDIC_Cosh(XMC_MATH_Q0_23_t angle_in_radians)334 XMC_MATH_Q1_22_t XMC_MATH_CORDIC_Cosh(XMC_MATH_Q0_23_t angle_in_radians)
335 {
336 int32_t result;
337 MATH->STATC = 0U; /* Clear register */
338 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_HYPERBOLIC + \
339 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
340 MATH->CORDZ = ((uint32_t) angle_in_radians) << MATH_CORDZ_DATA_Pos;
341 MATH->CORDY = 0U; /* Clear register */
342 MATH->CORDX = XMC_MATH_RECIPROC_HYPERBOLIC_GAIN_IN_Q1_22 << MATH_CORDX_DATA_Pos;
343 result = ((int32_t)MATH->CORRX) >> MATH_CORRX_RESULT_Pos;
344 return ((XMC_MATH_Q1_22_t) result);
345 }
346
347 /* This function computes the hyperbolic sine of a given angle in radians */
XMC_MATH_CORDIC_Sinh(XMC_MATH_Q0_23_t angle_in_radians)348 XMC_MATH_Q1_22_t XMC_MATH_CORDIC_Sinh(XMC_MATH_Q0_23_t angle_in_radians)
349 {
350 int32_t result;
351 MATH->STATC = 0U; /* Clear register */
352 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_HYPERBOLIC + \
353 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
354 MATH->CORDZ = ((uint32_t)angle_in_radians) << MATH_CORDZ_DATA_Pos;
355 MATH->CORDY = 0U; /* Clear register */
356 MATH->CORDX = XMC_MATH_RECIPROC_HYPERBOLIC_GAIN_IN_Q1_22 << MATH_CORDX_DATA_Pos;
357 result = ((int32_t)MATH->CORRY) >> MATH_CORRY_RESULT_Pos;
358 return ((XMC_MATH_Q1_22_t) result);
359 }
360
361 /* This function computes the hyperbolic tangent of a given angle in radians */
XMC_MATH_CORDIC_Tanh(XMC_MATH_Q0_23_t angle_in_radians)362 XMC_MATH_Q0_11_t XMC_MATH_CORDIC_Tanh(XMC_MATH_Q0_23_t angle_in_radians)
363 {
364 uint32_t result;
365 MATH->GLBCON = (uint32_t) XMC_MATH_DIV_DVDRC_CORRY_IS_SOURCE + \
366 (uint32_t) XMC_MATH_DIV_DVSRC_CORRX_IS_SOURCE; /* Chain the results of CORDIC operation to DIV unit */
367 MATH->DIVCON = (uint32_t) 11 << MATH_DIVCON_DVSSRC_Pos; /* Right Shifts Divisor by 11 places prior to division */
368 MATH->STATC = 0U; /* Clear register */
369 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_HYPERBOLIC + \
370 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
371 MATH->CORDZ = ((uint32_t) angle_in_radians) << MATH_CORDZ_DATA_Pos;
372 MATH->CORDY = 0U; /* Clear register */
373 MATH->CORDX = XMC_MATH_RECIPROC_HYPERBOLIC_GAIN_IN_Q1_22 << MATH_CORDX_DATA_Pos;
374 result = MATH->QUOT;
375 return ((XMC_MATH_Q0_11_t) result);
376 }
377
378 /***********************************************************************************************************************
379 * API IMPLEMENTATION - Non blocking functions
380 **********************************************************************************************************************/
381 /* This function computes the cosine of a given angle in radians */
XMC_MATH_CORDIC_CosNB(XMC_MATH_Q0_23_t angle_in_radians)382 void XMC_MATH_CORDIC_CosNB(XMC_MATH_Q0_23_t angle_in_radians)
383 {
384 MATH->STATC = 0U; /* Clear register */
385 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_CIRCULAR + \
386 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
387 MATH->CORDZ = ((uint32_t) angle_in_radians) << MATH_CORDZ_DATA_Pos;
388 MATH->CORDY = 0U; /* Clear register */
389 MATH->CORDX = XMC_MATH_RECIPROC_CIRCULAR_GAIN_IN_Q023 << MATH_CORDX_DATA_Pos;
390 }
391
392 /* This function computes the sine of a given angle in radians */
XMC_MATH_CORDIC_SinNB(XMC_MATH_Q0_23_t angle_in_radians)393 void XMC_MATH_CORDIC_SinNB(XMC_MATH_Q0_23_t angle_in_radians)
394 {
395 MATH->STATC = 0U; /* Clear register */
396 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_CIRCULAR + \
397 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
398 MATH->CORDZ = ((uint32_t)angle_in_radians) << MATH_CORDZ_DATA_Pos;
399 MATH->CORDY = 0U; /* Clear register */
400 MATH->CORDX = XMC_MATH_RECIPROC_CIRCULAR_GAIN_IN_Q023 << MATH_CORDX_DATA_Pos;
401 }
402
403 /* This function computes the tangent of a given angle in radians */
XMC_MATH_CORDIC_TanNB(XMC_MATH_Q0_23_t angle_in_radians)404 void XMC_MATH_CORDIC_TanNB(XMC_MATH_Q0_23_t angle_in_radians)
405 {
406 MATH->GLBCON = (uint32_t) XMC_MATH_DIV_DVDRC_CORRY_IS_SOURCE + \
407 (uint32_t) XMC_MATH_DIV_DVSRC_CORRX_IS_SOURCE; /* Chain the results of CORDIC operation to DIV unit */
408 MATH->DIVCON = (uint32_t) 11 << MATH_DIVCON_DVSSRC_Pos; /* Right Shifts Divisor by 11 places prior to division */
409
410 MATH->STATC = 0U; /* Clear register */
411 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_CIRCULAR + \
412 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
413 MATH->CORDZ = ((uint32_t)angle_in_radians) << MATH_CORDZ_DATA_Pos;
414 MATH->CORDY = 0U; /* Clear register */
415 MATH->CORDX = XMC_MATH_RECIPROC_CIRCULAR_GAIN_IN_Q023 << MATH_CORDX_DATA_Pos;
416 }
417
418 /* This function computes the arc tangent of a given value */
XMC_MATH_CORDIC_ArcTanNB(XMC_MATH_Q8_15_t x,XMC_MATH_Q8_15_t y)419 void XMC_MATH_CORDIC_ArcTanNB(XMC_MATH_Q8_15_t x, XMC_MATH_Q8_15_t y)
420 {
421 MATH->STATC = 0U; /* Clear register */
422 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_CIRCULAR;
423 MATH->CORDZ = 0U; /* Clear register */
424 MATH->CORDY = ((uint32_t) y) << MATH_CORDY_DATA_Pos;
425 MATH->CORDX = ((uint32_t) x) << MATH_CORDX_DATA_Pos;
426 }
427
428 /* This function computes the hyperbolic cosine of a given angle in radians */
XMC_MATH_CORDIC_CoshNB(XMC_MATH_Q0_23_t angle_in_radians)429 void XMC_MATH_CORDIC_CoshNB(XMC_MATH_Q0_23_t angle_in_radians)
430 {
431 MATH->STATC = 0U; /* Clear register */
432 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_HYPERBOLIC + \
433 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
434 MATH->CORDZ = ((uint32_t)angle_in_radians) << MATH_CORDZ_DATA_Pos;
435 MATH->CORDY = 0U; /* Clear register */
436 MATH->CORDX = XMC_MATH_RECIPROC_HYPERBOLIC_GAIN_IN_Q1_22 << MATH_CORDX_DATA_Pos;
437 }
438
439 /* This function computes the hyperbolic sine of a given angle in radians */
XMC_MATH_CORDIC_SinhNB(XMC_MATH_Q0_23_t angle_in_radians)440 void XMC_MATH_CORDIC_SinhNB(XMC_MATH_Q0_23_t angle_in_radians)
441 {
442 MATH->STATC = 0U; /* Clear register */
443 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_HYPERBOLIC + \
444 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
445 MATH->CORDZ = ((uint32_t)angle_in_radians) << MATH_CORDZ_DATA_Pos;
446 MATH->CORDY = 0U; /* Clear register */
447 MATH->CORDX = XMC_MATH_RECIPROC_HYPERBOLIC_GAIN_IN_Q1_22 << MATH_CORDX_DATA_Pos;
448 }
449
450 /* This function computes the hyperbolic tangent of a given angle in radians */
XMC_MATH_CORDIC_TanhNB(XMC_MATH_Q0_23_t angle_in_radians)451 void XMC_MATH_CORDIC_TanhNB(XMC_MATH_Q0_23_t angle_in_radians)
452 {
453 MATH->GLBCON = (uint32_t) XMC_MATH_DIV_DVDRC_CORRY_IS_SOURCE + \
454 (uint32_t) XMC_MATH_DIV_DVSRC_CORRX_IS_SOURCE; /* Chain the results of CORDIC operation to DIV unit */
455 MATH->DIVCON = (uint32_t) 11 << MATH_DIVCON_DVSSRC_Pos; /* Right Shifts Divisor by 11 places prior to division */
456 MATH->STATC = 0U; /* Clear register */
457 MATH->CON = (uint32_t) XMC_MATH_CORDIC_OPERATING_MODE_HYPERBOLIC + \
458 (uint32_t) XMC_MATH_CORDIC_ROTVEC_MODE_ROTATION;
459 MATH->CORDZ = ((uint32_t) angle_in_radians) << MATH_CORDZ_DATA_Pos;
460 MATH->CORDY = 0U; /* Clear register */
461 MATH->CORDX = XMC_MATH_RECIPROC_HYPERBOLIC_GAIN_IN_Q1_22 << MATH_CORDX_DATA_Pos;
462 }
463
464 /* This function performs division for given two unsigned arguments */
XMC_MATH_DIV_UnsignedDivNB(uint32_t dividend,uint32_t divisor)465 void XMC_MATH_DIV_UnsignedDivNB(uint32_t dividend, uint32_t divisor)
466 {
467 MATH->DIVCON = XMC_MATH_UNSIGNED_DIVISION;
468 MATH->DVD = dividend;
469 MATH->DVS = divisor;
470 }
471
472 /* This function performs division for given two signed arguments */
XMC_MATH_DIV_SignedDivNB(int32_t dividend,int32_t divisor)473 void XMC_MATH_DIV_SignedDivNB(int32_t dividend, int32_t divisor)
474 {
475 MATH->DIVCON = XMC_MATH_SIGNED_DIVISION;
476 MATH->DVD = dividend;
477 MATH->DVS = divisor;
478 }
479
480 /* This function performs modulo operation for given two unsigned arguments */
XMC_MATH_DIV_UnsignedModNB(uint32_t dividend,uint32_t divisor)481 void XMC_MATH_DIV_UnsignedModNB(uint32_t dividend, uint32_t divisor)
482 {
483 MATH->DIVCON = XMC_MATH_UNSIGNED_DIVISION;
484 MATH->DVD = dividend;
485 MATH->DVS = divisor;
486 }
487
488 /* This function performs modulo operation for given two signed arguments */
XMC_MATH_DIV_SignedModNB(int32_t dividend,int32_t divisor)489 void XMC_MATH_DIV_SignedModNB(int32_t dividend, int32_t divisor)
490 {
491 MATH->DIVCON = XMC_MATH_SIGNED_DIVISION;
492 MATH->DVD = dividend;
493 MATH->DVS = divisor;
494 }
495
XMC_MATH_CORDIC_Q15_Sqrt(int16_t x)496 int16_t XMC_MATH_CORDIC_Q15_Sqrt(int16_t x)
497 {
498 int32_t temp;
499 MATH->STATC = 0U; /* Clear register */
500
501 MATH->CON = (uint32_t)XMC_MATH_CORDIC_OPERATING_MODE_HYPERBOLIC |
502 (uint32_t)XMC_MATH_CORDIC_ROTVEC_MODE_VECTORING;
503
504 temp = (int32_t)x << 15; /* Q30 to handle numbers > 1.0 */
505
506 MATH->CORDY = (temp - 0x10000000U); /* x - 0.25 */
507 MATH->CORDX = (temp + 0x10000000U); /* x + 0.25 */
508
509 return (int16_t)(((MATH->CORRX >> 14) * 39568) >> 16); /* Q16 * Q15 */
510 }
511
XMC_MATH_CORDIC_Q31_Sqrt(int32_t x)512 int32_t XMC_MATH_CORDIC_Q31_Sqrt(int32_t x)
513 {
514 MATH->STATC = 0U; /* Clear register */
515
516 MATH->CON = (uint32_t)XMC_MATH_CORDIC_OPERATING_MODE_HYPERBOLIC |
517 (uint32_t)XMC_MATH_CORDIC_ROTVEC_MODE_VECTORING;
518
519 x >>= 1; /* Q30 to handle numbers > 1.0 */
520
521 MATH->CORDY = (x - 0x10000000U); /* x - 0.25 */
522 MATH->CORDX = (x + 0x10000000U); /* x + 0.25 */
523
524 return ((MATH->CORRX >> 14) * 39568); /* Q16 * Q15 */
525 }
526
527 #endif /* end of #if defined (MATH) */
528