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