1 /*
2  * SPDX-FileCopyrightText: 2019-2025 SiFli Technologies(Nanjing) Co., Ltd
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __BF0_HAL_MATH_H
8 #define __BF0_HAL_MATH_H
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #ifndef SF32LB52X
15 #if defined(__CC_ARM) || defined(__CLANG_ARM) || (defined(__GNUC__) && (__GNUC__ > 9))
16 #define HAL_MATH_CDE_SUPPORT
17 #endif /* defined(__CC_ARM) || defined(__CLANG_ARM) || (defined(__GNUC__) && (__GNUC__ > 9)) */
18 #endif /* SF32LB52X */
19 
20 /* Includes ------------------------------------------------------------------*/
21 #if defined(__CC_ARM) || defined(__ARMCC_VERSION)
22 #include <arm_acle.h>
23 #ifdef HAL_MATH_CDE_SUPPORT
24 #include <arm_cde.h>
25 #endif /* HAL_MATH_CDE_SUPPORT */
26 #elif defined(__ICCARM__)
27 #include <intrinsics.h>
28 #elif defined(__GNUC__)
29 #include <arm_acle.h>
30 #ifdef HAL_MATH_CDE_SUPPORT
31 #include <arm_cde.h>
32 #endif /* HAL_MATH_CDE_SUPPORT */
33 #endif /* defined(__CC_ARM) */
34 
35 #include "bf0_hal_def.h"
36 
37 /** @addtogroup MATH
38   * @ingroup BF0_HAL_Driver
39   * @{
40   */
41 
HAL_MATH_DisableInterrupt(void)42 __STATIC_INLINE uint32_t HAL_MATH_DisableInterrupt(void)
43 {
44     uint32_t mask;
45 
46     mask = __get_PRIMASK();
47     __set_PRIMASK(1);
48     return mask;
49 }
50 
HAL_MATH_EnableInterrupt(uint32_t mask)51 __STATIC_INLINE void HAL_MATH_EnableInterrupt(uint32_t mask)
52 {
53     __set_PRIMASK(mask);
54 }
55 
56 
57 /** normal coprocessor for math */
58 #define CP_MATH_NORMAL   (2)
59 /** coprocessor used by CDE */
60 #define CP_MATH_CDE      (1)
61 
62 #define CP_MATH_NORM_OP_SET_XY         (0)
63 #define CP_MATH_NORM_OP_SET_X          (0)
64 #define CP_MATH_NORM_OP_SET_Y          (1)
65 #define CP_MATH_NORM_OP_SET_ANGLE      (2)
66 #define CP_MATH_NORM_OP_SET_ITER_NUM   (3)
67 #define CP_MATH_NORM_OP_SET_SCALE      (4)
68 #define CP_MATH_NORM_OP_SET_MODE       (5)
69 
70 #define CP_MATH_NORM_MODE_COS          (1)
71 #define CP_MATH_NORM_MODE_SIN          (2)
72 #define CP_MATH_NORM_MODE_ATAN         (3)
73 #define CP_MATH_NORM_MODE_MOD          (4)
74 #define CP_MATH_NORM_MODE_ANG          (5)
75 #define CP_MATH_NORM_MODE_ROT          (6)
76 #define CP_MATH_NORM_MODE_MUL          (7)
77 #define CP_MATH_NORM_MODE_DIV          (8)
78 #define CP_MATH_NORM_MODE_COSH         (9)
79 #define CP_MATH_NORM_MODE_SINH         (10)
80 #define CP_MATH_NORM_MODE_ATANH        (11)
81 #define CP_MATH_NORM_MODE_MODH         (12)
82 #define CP_MATH_NORM_MODE_ANGH         (13)
83 #define CP_MATH_NORM_MODE_SQRT         (14)
84 #define CP_MATH_NORM_MODE_EXP          (15)
85 #define CP_MATH_NORM_MODE_LN           (16)
86 
87 #define CP_MATH_CDE_MODE_COS      (0)
88 #define CP_MATH_CDE_MODE_SIN      (0)
89 #define CP_MATH_CDE_MODE_ATAN     (0)
90 #define CP_MATH_CDE_MODE_MOD      (1)
91 #define CP_MATH_CDE_MODE_ANG      (2)
92 #define CP_MATH_CDE_MODE_ROT      (3)
93 #define CP_MATH_CDE_MODE_MUL      (4)
94 #define CP_MATH_CDE_MODE_DIV      (5)
95 #define CP_MATH_CDE_MODE_COSH     (6)
96 #define CP_MATH_CDE_MODE_SINH     (7)
97 #define CP_MATH_CDE_MODE_ATANH    (8)
98 #define CP_MATH_CDE_MODE_MODH     (9)
99 #define CP_MATH_CDE_MODE_ANGH     (10)
100 #define CP_MATH_CDE_MODE_SQRT     (11)
101 #define CP_MATH_CDE_MODE_EXP      (12)
102 #define CP_MATH_CDE_MODE_LN       (13)
103 
104 
105 /**
106  * @brief  Move x and y to 64bit register, y is put in high 32bit and x is put in low 32bit
107  *
108  * @param[in] x x value
109  * @param[in] y y value
110  *
111  * @return void
112  */
113 #define CP_MATH_SET_XY(x,y)       __arm_mcrr(CP_MATH_NORMAL, CP_MATH_NORM_OP_SET_XY, (((uint64_t)((uint32_t)(y))) << 32) | ((uint32_t)(x)), 0)
114 #define CP_MATH_SET_X(x)          __arm_mcr(CP_MATH_NORMAL, CP_MATH_NORM_OP_SET_X, (x), 0, 0, 0)
115 #define CP_MATH_SET_Y(y)          __arm_mcr(CP_MATH_NORMAL, CP_MATH_NORM_OP_SET_Y, (y), 0, 0, 0)
116 #define CP_MATH_SET_ANGLE(angle)  __arm_mcr(CP_MATH_NORMAL, CP_MATH_NORM_OP_SET_ANGLE, (angle), 0, 1, 2)
117 #define CP_MATH_SET_ITER_NUM(num) __arm_mcr(CP_MATH_NORMAL, CP_MATH_NORM_OP_SET_ITER_NUM, (num), 0, 1, 3)
118 #define CP_MATH_SET_SCALE(scale)  __arm_mcr(CP_MATH_NORMAL, CP_MATH_NORM_OP_SET_SCALE, (scale), 0, 0, 0)
119 #define CP_MATH_SET_MODE(mode)    __arm_mcr(CP_MATH_NORMAL, CP_MATH_NORM_OP_SET_MODE, (mode), 0, 1, 4)
120 
121 #define CP_MATH_GET_RESULT_UINT64() __arm_mrrc(CP_MATH_NORMAL, 0, 0)
122 #define CP_MATH_GET_SCALE_AND_VAL(arg_result, arg_scale, arg_val)   \
123     do                                                  \
124     {                                                   \
125         if (arg_scale)                                  \
126         {                                               \
127             *arg_scale = (int8_t)((arg_result >> 32) & UINT8_MAX);  \
128         }                                                           \
129         if (arg_val)                                                \
130         {                                                           \
131             *arg_val = (int32_t)(arg_result & UINT32_MAX);          \
132         }                                                           \
133     }                                                               \
134     while (0)
135 
136 #define CP_MATH_CDE_MAKE_CTRL_CODE(mode, iter_num)   ((((uint8_t)mode) & 0xF) | (((uint8_t)iter_num & 0x1F) << 4))
137 
138 
139 /**
140  * @brief  Calculate cosine and sine of an angle
141  *
142  * @param[in] angle angle in radians, devided by pi, Q1.31 format, range: [-1, 1], it's mapped to [-pi, pi]
143  * @param[out] cos_val cosine of the angle, Q1.31 format
144  * @param[out] sin_val sine of the angle, Q1.31 format
145  *
146  * @retval cosine value
147  */
HAL_CP_CosSin(int32_t angle,int32_t * cos_val,int32_t * sin_val)148 __STATIC_INLINE void HAL_CP_CosSin(int32_t angle, int32_t *cos_val, int32_t *sin_val)
149 {
150     uint64_t cos_sin;
151 
152     CP_MATH_SET_ANGLE(angle);
153     CP_MATH_SET_ITER_NUM(11);
154     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_COS);
155 
156     cos_sin = CP_MATH_GET_RESULT_UINT64();
157     if (cos_val)
158     {
159         *cos_val = (int32_t)(cos_sin & UINT32_MAX);
160     }
161     if (sin_val)
162     {
163         *sin_val = (int32_t)((cos_sin >> 32) & UINT32_MAX);
164     }
165 
166     return;
167 }
168 
169 /**
170  * @brief  Calculate sine of an angle
171  *
172  * @param[in] angle angle in radians, devided by pi, Q1.31 format, range: [-1, 1], it's mapped to [-pi, pi]
173  *
174  * @retval sine value in Q1.31 format
175  */
HAL_CP_Sin(int32_t angle)176 __STATIC_INLINE int32_t HAL_CP_Sin(int32_t angle)
177 {
178     int32_t result;
179 
180     CP_MATH_SET_ANGLE(angle);
181     CP_MATH_SET_ITER_NUM(11);
182     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_SIN);
183 
184     result = (int32_t)(CP_MATH_GET_RESULT_UINT64() & UINT32_MAX);
185 
186     return result;
187 }
188 
189 /**
190  * @brief  Calculate arctangent
191  *         formula: atan*pi=atan(data*(2^scale))
192  *
193  * @param[in] scale scaling factor, range is [0,12]
194  * @param[in] data data in Q1.31 format
195  *
196  * @retval arctangent in radians, divided by pi, Q1.31 format, range is [-1, 1] which is mapped to [-pi, pi]
197  */
HAL_CP_Atan(int8_t scale,int32_t data)198 __STATIC_INLINE int32_t HAL_CP_Atan(int8_t scale, int32_t data)
199 {
200     int32_t result;
201 
202     CP_MATH_SET_Y(data);
203     CP_MATH_SET_ITER_NUM(11);
204     CP_MATH_SET_SCALE(scale);
205     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_ATAN);
206 
207     result = (int32_t)(CP_MATH_GET_RESULT_UINT64() & UINT32_MAX);
208     return result;
209 }
210 
211 /**
212  * @brief  Calculate magnitude(i.e. modulus) of the vector v=(x,y),
213  *         formula: magnitude=mod*(2^scale)=sqrt(x^2 + y^2)
214  *
215  * @param[in] x x coordinate, Q1.31 format
216  * @param[in] y y coordinate, Q1.31 format
217  * @param[out] scale points to output scaling value, range is [-30, 1]
218  * @param[out] mod points to output modulus, Q1.31 format
219  *
220  * @retval void
221  */
HAL_CP_Mod(int32_t x,int32_t y,int8_t * scale,int32_t * mod)222 __STATIC_INLINE void HAL_CP_Mod(int32_t x, int32_t y, int8_t *scale, int32_t *mod)
223 {
224     uint64_t result ;
225 
226     CP_MATH_SET_XY(x, y);
227     CP_MATH_SET_ITER_NUM(11);
228     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_MOD);
229 
230     result = CP_MATH_GET_RESULT_UINT64();
231     CP_MATH_GET_SCALE_AND_VAL(result, scale, mod);
232 
233     return;
234 }
235 
236 /**
237  * @brief  Calculate phase angle of the vector v=(x,y),
238  *         formula: angle*pi=arctangent(y/x)
239  *
240  * @param[in] x x coordinate, Q1.31 format
241  * @param[in] y y coordinate, Q1.31 format
242  *
243  * @retval angle in radians devided by pi, range is [-1,1] which is mapped to [-pi, pi]
244  */
HAL_CP_Ang(int32_t x,int32_t y)245 __STATIC_INLINE int32_t HAL_CP_Ang(int32_t x, int32_t y)
246 {
247     uint64_t result ;
248 
249     CP_MATH_SET_XY(x, y);
250     CP_MATH_SET_ITER_NUM(11);
251     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_ANG);
252 
253     result = CP_MATH_GET_RESULT_UINT64();
254     return (result & UINT32_MAX);
255 }
256 
257 /**
258  * @brief  Calculate the rotated vector
259  *
260  * @param[in] x x coordinate, Q1.31 format, range is (-0.707, 0.707)
261  * @param[in] y y coordinate, Q1.31 format, range is (-0.707, 0.707)
262  * @param[in] angle angle in radians, devided by pi, Q1.31 format, range: [-1, 1], which is mapped to [-pi, pi]
263  * @param[out] x2 points to x coordinate of the rotated vector
264  * @param[out] y2 points to y coordinate of the rotated vector
265 
266  * @return void
267  */
HAL_CP_Rot(int32_t x,int32_t y,int32_t angle,int32_t * x2,int32_t * y2)268 __STATIC_INLINE void HAL_CP_Rot(int32_t x, int32_t y, int32_t angle, int32_t *x2, int32_t *y2)
269 {
270     uint64_t result;
271 
272     CP_MATH_SET_XY(x, y);
273     CP_MATH_SET_ANGLE(angle);
274     CP_MATH_SET_ITER_NUM(11);
275     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_ROT);
276 
277     result = CP_MATH_GET_RESULT_UINT64();
278     if (x2)
279     {
280         *x2 = (int32_t)(result & UINT32_MAX);
281     }
282     if (y2)
283     {
284         *y2 = (int32_t)(result >> 32);
285     }
286 
287     return;
288 }
289 
290 /**
291  * @brief  Multiple data0 by data1
292  *         formula: val*(2^scale)=data0*data1
293  *
294  * @param[in] data0 data0 in Q1.31 format
295  * @param[in] data1 data1 in Q1.31 format
296  * @param[out] scale points to scaling factor, Q8.0 format, range is [-60,0]
297  * @param[out] val points to output value, Q1.31 format
298 
299  * @return void
300  */
HAL_CP_Mul(int32_t data0,int32_t data1,int8_t * scale,int32_t * val)301 __STATIC_INLINE void HAL_CP_Mul(int32_t data0, int32_t data1, int8_t *scale, int32_t *val)
302 {
303     uint64_t result;
304 
305     CP_MATH_SET_XY(data0, data1);
306     CP_MATH_SET_ITER_NUM(11);
307     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_MUL);
308 
309     result = CP_MATH_GET_RESULT_UINT64();
310     CP_MATH_GET_SCALE_AND_VAL(result, scale, val);
311 
312     return;
313 }
314 
315 
316 /**
317  * @brief  Divide numeritor by denominator
318  *         formula: num/den=val*(2^scale)
319  *
320  * @param[in] num numerator in Q1.31 format
321  * @param[in] den denominator in Q1.31 format
322  * @param[out] scale points to scaling factor, Q8.0 format, range is [-30,30]
323  * @param[out] val points to output vallue, Q1.31 format
324 
325  * @return void
326  */
HAL_CP_Div(int32_t num,int32_t den,int8_t * scale,int32_t * val)327 __STATIC_INLINE void HAL_CP_Div(int32_t num, int32_t den, int8_t *scale, int32_t *val)
328 {
329     uint64_t result;
330 
331     CP_MATH_SET_XY(den, num);
332     CP_MATH_SET_ITER_NUM(11);
333     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_DIV);
334 
335     result = CP_MATH_GET_RESULT_UINT64();
336     CP_MATH_GET_SCALE_AND_VAL(result, scale, val);
337 
338     return;
339 }
340 
341 /**
342  * @brief  Calculate cosineh of an angle
343  *         formula: cosh*(2^output_scale)=cosh(angle*(2^scale)),
344  *                  angle*(2^scale) range is (-1.118, 1.118)
345  *
346  * @param[in] scale scaling factor, Q8.0 format, range is [0, 1]
347  * @param[in] angle angle in Q1.31 format, range: [-1, 1)
348  * @param[out] output_scale points to output scaling factor, Q8.0 format, range is [0, 1]
349  * @param[out] cosh points to output cosh value
350  *
351  * @return void
352  */
HAL_CP_Cosh(int8_t scale,int32_t angle,int8_t * output_scale,int32_t * cosh)353 __STATIC_INLINE void HAL_CP_Cosh(int8_t scale, int32_t angle, int8_t *output_scale, int32_t *cosh)
354 {
355     uint64_t result;
356 
357     CP_MATH_SET_ANGLE(angle);
358     CP_MATH_SET_SCALE(scale);
359     CP_MATH_SET_ITER_NUM(12);
360     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_COSH);
361 
362     result = CP_MATH_GET_RESULT_UINT64();
363     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, cosh);
364 
365     return;
366 }
367 
368 /**
369  * @brief  Calculate sineh of an angle
370  *         formula: sinh*(2^output_scale)=sinh(angle*(2^scale)),
371  *                  angle*(2^scale) range is (-1.118, 1.118)
372  *
373  * @param[in] scale scaling factor, Q8.0 format, range is [0,1]
374  * @param[in] angle angle in Q1.31 format, range: [-1, 1)
375  * @param[out] output_scale points to output scaling factor, Q8.0 format, range is [0, 1]
376  * @param[out] sinh points to output sinh value
377  *
378  * @return void
379  */
HAL_CP_Sinh(int8_t scale,int32_t angle,int8_t * output_scale,int32_t * sinh)380 __STATIC_INLINE void HAL_CP_Sinh(int8_t scale, int32_t angle, int8_t *output_scale, int32_t *sinh)
381 {
382     uint64_t result;
383 
384     CP_MATH_SET_ANGLE(angle);
385     CP_MATH_SET_SCALE(scale);
386     CP_MATH_SET_ITER_NUM(12);
387     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_SINH);
388 
389     result = CP_MATH_GET_RESULT_UINT64();
390     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, sinh);
391 
392     return;
393 }
394 
395 /**
396  * @brief  Calculate atanh of data, data range is (-0.806, 0.806)
397  *         formula: atanh*(2^scale)=atanh(data)
398  *
399  * @param[in] data data in Q1.31 format
400  * @param[out] scale points to output scaling factor, Q8.0 format, range is [0, 1]
401  * @param[out] atanh points to output atanh value
402  *
403  * @return void
404  */
HAL_CP_Atanh(int32_t data,int8_t * scale,int32_t * atanh)405 __STATIC_INLINE void HAL_CP_Atanh(int32_t data, int8_t *scale, int32_t *atanh)
406 {
407     uint64_t result;
408 
409     CP_MATH_SET_Y(data);
410     CP_MATH_SET_ITER_NUM(12);
411     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_ATANH);
412 
413     result = CP_MATH_GET_RESULT_UINT64();
414     CP_MATH_GET_SCALE_AND_VAL(result, scale, atanh);
415 
416     return;
417 }
418 
419 /**
420  * @brief  Calculate sqrt(x^2-y^2)
421  *         modh*(2^scale)=sqrt(x^2-y^2),
422  *         x range is (-1, 1), y range is (-0.806, 0.806), and abs(x)>=abs(y)
423  *
424  * @param[in] x x coordinate, Q1.31 format
425  * @param[in] y y coordinate, Q1.31 format
426  * @param[out] scale points to output scaling factor in Q8.0 format
427  * @param[out] modh points to output modulush, Q1.31 format
428  *
429  * @return void
430  */
HAL_CP_Modh(int32_t x,int32_t y,int8_t * scale,int32_t * modh)431 __STATIC_INLINE void HAL_CP_Modh(int32_t x, int32_t y, int8_t *scale, int32_t *modh)
432 {
433     uint64_t result;
434 
435     CP_MATH_SET_XY(x, y);
436     CP_MATH_SET_ITER_NUM(12);
437     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_MODH);
438 
439     result = CP_MATH_GET_RESULT_UINT64();
440     CP_MATH_GET_SCALE_AND_VAL(result, scale, modh);
441 
442     return;
443 }
444 
445 /**
446  * @brief  Calculate arctanh(y/x)
447  *         angh*(2^scale)=arctanh(y/x),
448  *         x range is (-1, 1), y range is (-0.806, 0.806), and abs(x)>=abs(y)
449  *
450  * @param[in] x x coordinate, Q1.31 format
451  * @param[in] y y coordinate, Q1.31 format
452  * @param[out] scale points to output scaling factor in Q8.0 format
453  * @param[out] angh points to output angh, Q1.31 format
454  *
455  * @return void
456  */
HAL_CP_Angh(int32_t x,int32_t y,int8_t * scale,int32_t * angh)457 __STATIC_INLINE void HAL_CP_Angh(int32_t x, int32_t y, int8_t *scale, int32_t *angh)
458 {
459     uint64_t result;
460 
461     CP_MATH_SET_XY(x, y);
462     CP_MATH_SET_ITER_NUM(12);
463     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_ANGH);
464 
465     result = CP_MATH_GET_RESULT_UINT64();
466     CP_MATH_GET_SCALE_AND_VAL(result, scale, angh);
467 
468     return;
469 }
470 
471 /**
472  * @brief  Square root
473  *         formula: output_val*(2^output_scale)=sqrt(input_val*(2^input_scale)),
474  *         input_val*(2^input_scale) range is (0.027, 2.34)
475  *
476  * @param[in] input_scale input scaling factor in Q8.0 format, range is [0, 2]
477  * @param[in] input_val input value in Q1.31 format
478  * @param[out] output_scale ponits to output scaling factor in Q8.0 format, range is [0, 2]
479  * @param[out] output_val points to output value in Q1.31 format
480  *
481  * @return void
482  */
HAL_CP_Sqrt(int8_t input_scale,int32_t input_val,int8_t * output_scale,int32_t * output_val)483 __STATIC_INLINE void HAL_CP_Sqrt(int8_t input_scale, int32_t input_val, int8_t *output_scale, int32_t *output_val)
484 {
485     uint64_t result;
486 
487     CP_MATH_SET_X(input_val);
488     CP_MATH_SET_SCALE(input_scale);
489     CP_MATH_SET_ITER_NUM(12);
490     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_SQRT);
491 
492     result = CP_MATH_GET_RESULT_UINT64();
493     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, output_val);
494     return;
495 }
496 
497 /**
498  * @brief  Exp of the given value
499  *         formula: output_val*(2^output_scale)=exp(input_val*(2^input_scale)),
500  *                  input_val*(2^input_scale) range is (-1.118, 1.118)
501  *
502  * @param[in] input_scale input scaling factor in Q8.0 format, range is [0, 1]
503  * @param[in] input_val input value in Q1.31 format
504  * @param[out] output_scale ponits to output scaling factor in Q8.0 format, range is [0, 2]
505  * @param[out] output_val points to output value in Q1.31 format
506  *
507  * @return void
508  */
HAL_CP_Exp(int8_t input_scale,int32_t input_val,int8_t * output_scale,int32_t * output_val)509 __STATIC_INLINE void HAL_CP_Exp(int8_t input_scale, int32_t input_val, int8_t *output_scale, int32_t *output_val)
510 {
511     uint64_t result;
512 
513     CP_MATH_SET_ANGLE(input_val);
514     CP_MATH_SET_SCALE(input_scale);
515     CP_MATH_SET_ITER_NUM(12);
516     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_EXP);
517 
518     result = CP_MATH_GET_RESULT_UINT64();
519     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, output_val);
520 
521     return;
522 }
523 
524 /**
525  * @brief  Ln of the given value
526  *         formula: output_val*(2^output_scale)=ln(input_val*(2^input_scale)),
527                     input_val*(2^input_scale) range is (0.107, 9.35)
528  *
529  * @param[in] input_scale input scaling factor in Q8.0 format, range is [0, 4]
530  * @param[in] input_val input value in Q1.31 format
531  * @param[out] output_scale ponits to output scaling factor in Q8.0 format, range is [1, 2]
532  * @param[out] output_val points to output value in Q1.31 format
533  *
534  * @return void
535  */
HAL_CP_Ln(int8_t input_scale,int32_t input_val,int8_t * output_scale,int32_t * output_val)536 __STATIC_INLINE void HAL_CP_Ln(int8_t input_scale, int32_t input_val, int8_t *output_scale, int32_t *output_val)
537 {
538     uint64_t result;
539 
540     CP_MATH_SET_X(input_val);
541     CP_MATH_SET_SCALE(input_scale);
542     CP_MATH_SET_ITER_NUM(12);
543     CP_MATH_SET_MODE(CP_MATH_NORM_MODE_LN);
544 
545     result = CP_MATH_GET_RESULT_UINT64();
546     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, output_val);
547 
548     return;
549 }
550 
551 
552 #ifdef HAL_MATH_CDE_SUPPORT
553 /**
554  * @brief  Calculate cosine and sine of an angle
555  *
556  * @param[in] angle angle in radians, devided by pi, Q1.31 format, range: [-1, 1], it's mapped to [-pi, pi]
557  * @param[out] cos_val cosine of the angle, Q1.31 format
558  * @param[out] sin_val sine of the angle, Q1.31 format
559  *
560  * @retval cosine value
561  */
HAL_CDE_CosSin(int32_t angle,int32_t * cos_val,int32_t * sin_val)562 __STATIC_INLINE void HAL_CDE_CosSin(int32_t angle, int32_t *cos_val, int32_t *sin_val)
563 {
564     volatile uint64_t cos_sin;
565     uint32_t mask;
566 
567     mask = HAL_MATH_DisableInterrupt();
568     cos_sin = __arm_cx2d(CP_MATH_CDE, angle,
569                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_COS, 11));
570     HAL_MATH_EnableInterrupt(mask);
571 
572     if (cos_val)
573     {
574         *cos_val = (int32_t)(cos_sin & UINT32_MAX);
575     }
576     if (sin_val)
577     {
578         *sin_val = (int32_t)((cos_sin >> 32) & UINT32_MAX);
579     }
580 
581     return;
582 }
583 
584 /**
585  * @brief  Calculate sine of an angle
586  *
587  * @param[in] angle angle in radians, devided by pi, Q1.31 format, range: [-1, 1], it's mapped to [-pi, pi]
588  *
589  * @retval sine value in Q1.31 format
590  */
HAL_CDE_Sin(int32_t angle)591 __STATIC_INLINE int32_t HAL_CDE_Sin(int32_t angle)
592 {
593     volatile int32_t result;
594     uint32_t mask;
595 
596     mask = HAL_MATH_DisableInterrupt();
597     result = (int32_t)__arm_cx2(CP_MATH_CDE, angle,
598                                 CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_SIN, 11));
599     HAL_MATH_EnableInterrupt(mask);
600 
601     return result;
602 }
603 
604 /**
605  * @brief  Calculate arctangent
606  *         formula: atan*pi=atan(data*(2^scale))
607  *
608  * @param[in] scale scaling factor, range is [0,12]
609  * @param[in] data data in Q1.31 format
610  *
611  * @retval arctangent in radians, divided by pi, Q1.31 format, range is [-1, 1] which is mapped to [-pi, pi]
612  */
HAL_CDE_Atan(int8_t scale,int32_t data)613 __STATIC_INLINE int32_t HAL_CDE_Atan(int8_t scale, int32_t data)
614 {
615     volatile int32_t result;
616     uint32_t mask;
617 
618     mask = HAL_MATH_DisableInterrupt();
619     result = (int32_t)(__arm_cx2da(CP_MATH_CDE, scale, data,
620                                    CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_ATAN, 11)) & UINT32_MAX);
621     HAL_MATH_EnableInterrupt(mask);
622 
623     return result;
624 }
625 
626 /**
627  * @brief  Calculate magnitude(i.e. modulus) of the vector v=(x,y),
628  *         formula: magnitude=mod*(2^scale)=sqrt(x^2 + y^2)
629  *
630  * @param[in] x x coordinate, Q1.31 format
631  * @param[in] y y coordinate, Q1.31 format
632  * @param[out] scale points to output scaling value, range is [-30, 1]
633  * @param[out] mod points to output modulus, Q1.31 format
634  *
635  * @retval void
636  */
HAL_CDE_Mod(int32_t x,int32_t y,int8_t * scale,int32_t * mod)637 __STATIC_INLINE void HAL_CDE_Mod(int32_t x, int32_t y, int8_t *scale, int32_t *mod)
638 {
639     volatile uint64_t result;
640     uint32_t mask;
641 
642     mask = HAL_MATH_DisableInterrupt();
643     result = __arm_cx2da(CP_MATH_CDE, y, x,
644                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_MOD, 11));
645     HAL_MATH_EnableInterrupt(mask);
646 
647     CP_MATH_GET_SCALE_AND_VAL(result, scale, mod);
648 
649     return;
650 }
651 
652 /**
653  * @brief  Calculate phase angle of the vector v=(x,y),
654  *         formula: angle*pi=arctangent(y/x)
655  *
656  * @param[in] x x coordinate, Q1.31 format
657  * @param[in] y y coordinate, Q1.31 format
658  *
659  * @retval angle in radians devided by pi, range is [-1,1] which is mapped to [-pi, pi]
660  */
HAL_CDE_Ang(int32_t x,int32_t y)661 __STATIC_INLINE int32_t HAL_CDE_Ang(int32_t x, int32_t y)
662 {
663     volatile uint64_t result;
664     uint32_t mask;
665 
666     mask = HAL_MATH_DisableInterrupt();
667     result = __arm_cx2da(CP_MATH_CDE, y, x,
668                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_ANG, 11));
669     HAL_MATH_EnableInterrupt(mask);
670 
671     return (result & UINT32_MAX);
672 }
673 
674 /**
675  * @brief  Calculate the rotated vector
676  *
677  * @param[in] x x coordinate, Q1.31 format, range is (-0.707, 0.707)
678  * @param[in] y y coordinate, Q1.31 format, range is (-0.707, 0.707)
679  * @param[in] angle angle in radians, devided by pi, Q1.31 format, range: [-1, 1], which is mapped to [-pi, pi]
680  * @param[out] x2 points to x coordinate of the rotated vector
681  * @param[out] y2 points to y coordinate of the rotated vector
682 
683  * @return void
684  */
HAL_CDE_Rot(int32_t x,int32_t y,int32_t angle,int32_t * x2,int32_t * y2)685 __STATIC_INLINE void HAL_CDE_Rot(int32_t x, int32_t y, int32_t angle, int32_t *x2, int32_t *y2)
686 {
687     volatile uint64_t result;
688     uint32_t mask;
689 
690     result = (uint64_t)((uint32_t)angle);
691     result = (result << 32) | (uint32_t)y;
692 
693     mask = HAL_MATH_DisableInterrupt();
694     result = __arm_cx2da(CP_MATH_CDE, result, x,
695                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_ROT, 11));
696     HAL_MATH_EnableInterrupt(mask);
697 
698     if (x2)
699     {
700         *x2 = (int32_t)(result & UINT32_MAX);
701     }
702     if (y2)
703     {
704         *y2 = (int32_t)(result >> 32);
705     }
706 
707     return;
708 }
709 
710 /**
711  * @brief  Multiple data0 by data1
712  *         formula: val*(2^scale)=data0*data1
713  *
714  * @param[in] data0 data0 in Q1.31 format
715  * @param[in] data1 data1 in Q1.31 format
716  * @param[out] scale points to scaling factor, Q8.0 format, range is [-60,0]
717  * @param[out] val points to output value, Q1.31 format
718 
719  * @return void
720  */
HAL_CDE_Mul(int32_t data0,int32_t data1,int8_t * scale,int32_t * val)721 __STATIC_INLINE void HAL_CDE_Mul(int32_t data0, int32_t data1, int8_t *scale, int32_t *val)
722 {
723     volatile uint64_t result;
724     uint32_t mask;
725 
726     mask = HAL_MATH_DisableInterrupt();
727     result = __arm_cx2da(CP_MATH_CDE, data1, data0,
728                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_MUL, 11));
729     HAL_MATH_EnableInterrupt(mask);
730 
731     CP_MATH_GET_SCALE_AND_VAL(result, scale, val);
732     return;
733 }
734 
735 
736 /**
737  * @brief  Divide numeritor by denominator
738  *         formula: num/den=val*(2^scale)
739  *
740  * @param[in] num numerator in Q1.31 format
741  * @param[in] den denominator in Q1.31 format
742  * @param[out] scale points to scaling factor, Q8.0 format, range is [-30,30]
743  * @param[out] val points to output vallue, Q1.31 format
744 
745  * @return void
746  */
HAL_CDE_Div(int32_t num,int32_t den,int8_t * scale,int32_t * val)747 __STATIC_INLINE void HAL_CDE_Div(int32_t num, int32_t den, int8_t *scale, int32_t *val)
748 {
749     volatile uint64_t result;
750     uint32_t mask;
751 
752     mask = HAL_MATH_DisableInterrupt();
753     result = __arm_cx2da(CP_MATH_CDE, num, den,
754                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_DIV, 11));
755     HAL_MATH_EnableInterrupt(mask);
756 
757     CP_MATH_GET_SCALE_AND_VAL(result, scale, val);
758 
759     return;
760 }
761 
762 /**
763  * @brief  Calculate cosineh of an angle
764  *         formula: cosh*(2^output_scale)=cosh(angle*(2^scale)),
765  *                  angle*(2^scale) range is (-1.118, 1.118)
766  *
767  * @param[in] scale scaling factor, Q8.0 format, range is [0, 1]
768  * @param[in] angle angle in Q1.31 format, range: [-1, 1)
769  * @param[out] output_scale points to output scaling factor, Q8.0 format, range is [0, 1]
770  * @param[out] cosh points to output cosh value
771  *
772  * @return void
773  */
HAL_CDE_Cosh(int8_t scale,int32_t angle,int8_t * output_scale,int32_t * cosh)774 __STATIC_INLINE void HAL_CDE_Cosh(int8_t scale, int32_t angle, int8_t *output_scale, int32_t *cosh)
775 {
776     volatile uint64_t result;
777     uint32_t mask;
778 
779     mask = HAL_MATH_DisableInterrupt();
780     result = __arm_cx2da(CP_MATH_CDE, scale, angle,
781                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_COSH, 12));
782     HAL_MATH_EnableInterrupt(mask);
783 
784     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, cosh);
785 
786     return;
787 }
788 
789 /**
790  * @brief  Calculate sineh of an angle
791  *         formula: sinh*(2^output_scale)=sinh(angle*(2^scale)),
792  *                  angle*(2^scale) range is (-1.118, 1.118)
793  *
794  * @param[in] scale scaling factor, Q8.0 format, range is [0,1]
795  * @param[in] angle angle in Q1.31 format, range: [-1, 1)
796  * @param[out] output_scale points to output scaling factor, Q8.0 format, range is [0, 1]
797  * @param[out] sinh points to output sinh value
798  *
799  * @return void
800  */
HAL_CDE_Sinh(int8_t scale,int32_t angle,int8_t * output_scale,int32_t * sinh)801 __STATIC_INLINE void HAL_CDE_Sinh(int8_t scale, int32_t angle, int8_t *output_scale, int32_t *sinh)
802 {
803     volatile uint64_t result;
804     uint32_t mask;
805 
806     mask = HAL_MATH_DisableInterrupt();
807     result = __arm_cx2da(CP_MATH_CDE, scale, angle,
808                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_SINH, 12));
809     HAL_MATH_EnableInterrupt(mask);
810 
811     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, sinh);
812 
813     return;
814 }
815 
816 /**
817  * @brief  Calculate atanh of data, data range is (-0.806, 0.806)
818  *         formula: atanh*(2^scale)=atanh(data)
819  *
820  * @param[in] data data in Q1.31 format
821  * @param[out] scale points to output scaling factor, Q8.0 format, range is [0, 1]
822  * @param[out] atanh points to output atanh value
823  *
824  * @return void
825  */
HAL_CDE_Atanh(int32_t data,int8_t * scale,int32_t * atanh)826 __STATIC_INLINE void HAL_CDE_Atanh(int32_t data, int8_t *scale, int32_t *atanh)
827 {
828     volatile uint64_t result;
829     uint32_t mask;
830 
831     mask = HAL_MATH_DisableInterrupt();
832     result = __arm_cx2da(CP_MATH_CDE, 0, data,
833                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_ATANH, 12));
834     HAL_MATH_EnableInterrupt(mask);
835 
836     CP_MATH_GET_SCALE_AND_VAL(result, scale, atanh);
837 
838     return;
839 }
840 
841 /**
842  * @brief  Calculate sqrt(x^2-y^2)
843  *         modh*(2^scale)=sqrt(x^2-y^2),
844  *         x range is (-1, 1), y range is (-0.806, 0.806), and abs(x)>=abs(y)
845  *
846  * @param[in] x x coordinate, Q1.31 format
847  * @param[in] y y coordinate, Q1.31 format
848  * @param[out] scale points to output scaling factor in Q8.0 format
849  * @param[out] modh points to output modulush, Q1.31 format
850  *
851  * @return void
852  */
HAL_CDE_Modh(int32_t x,int32_t y,int8_t * scale,int32_t * modh)853 __STATIC_INLINE void HAL_CDE_Modh(int32_t x, int32_t y, int8_t *scale, int32_t *modh)
854 {
855     volatile uint64_t result;
856     uint32_t mask;
857 
858     mask = HAL_MATH_DisableInterrupt();
859     result = __arm_cx2da(CP_MATH_CDE, y, x,
860                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_MODH, 12));
861     HAL_MATH_EnableInterrupt(mask);
862 
863     CP_MATH_GET_SCALE_AND_VAL(result, scale, modh);
864 
865     return;
866 }
867 
868 /**
869  * @brief  Calculate arctanh(y/x)
870  *         angh*(2^scale)=arctanh(y/x),
871  *         x range is (-1, 1), y range is (-0.806, 0.806), and abs(x)>=abs(y)
872  *
873  * @param[in] x x coordinate, Q1.31 format
874  * @param[in] y y coordinate, Q1.31 format
875  * @param[out] scale points to output scaling factor in Q8.0 format
876  * @param[out] angh points to output angh, Q1.31 format
877  *
878  * @return void
879  */
HAL_CDE_Angh(int32_t x,int32_t y,int8_t * scale,int32_t * angh)880 __STATIC_INLINE void HAL_CDE_Angh(int32_t x, int32_t y, int8_t *scale, int32_t *angh)
881 {
882     volatile uint64_t result;
883     uint32_t mask;
884 
885     mask = HAL_MATH_DisableInterrupt();
886     result = __arm_cx2da(CP_MATH_CDE, y, x,
887                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_ANGH, 12));
888     HAL_MATH_EnableInterrupt(mask);
889 
890     CP_MATH_GET_SCALE_AND_VAL(result, scale, angh);
891 
892     return;
893 }
894 
895 /**
896  * @brief  Square root
897  *         formula: output_val*(2^output_scale)=sqrt(input_val*(2^input_scale)),
898  *         input_val*(2^input_scale) range is (0.027, 2.34)
899  *
900  * @param[in] input_scale input scaling factor in Q8.0 format, range is [0, 2]
901  * @param[in] input_val input value in Q1.31 format
902  * @param[out] output_scale ponits to output scaling factor in Q8.0 format, range is [0, 2]
903  * @param[out] output_val points to output value in Q1.31 format
904  *
905  * @return void
906  */
HAL_CDE_Sqrt(int8_t input_scale,int32_t input_val,int8_t * output_scale,int32_t * output_val)907 __STATIC_INLINE void HAL_CDE_Sqrt(int8_t input_scale, int32_t input_val, int8_t *output_scale, int32_t *output_val)
908 {
909     volatile uint64_t result;
910     uint32_t mask;
911 
912     mask = HAL_MATH_DisableInterrupt();
913     result = __arm_cx2da(CP_MATH_CDE, input_scale, input_val,
914                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_SQRT, 12));
915     HAL_MATH_EnableInterrupt(mask);
916 
917     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, output_val);
918 
919     return;
920 }
921 
922 /**
923  * @brief  Exp of the given value
924  *         formula: output_val*(2^output_scale)=exp(input_val*(2^input_scale)),
925  *                  input_val*(2^input_scale) range is (-1.118, 1.118)
926  *
927  * @param[in] input_scale input scaling factor in Q8.0 format, range is [0, 1]
928  * @param[in] input_val input value in Q1.31 format
929  * @param[out] output_scale ponits to output scaling factor in Q8.0 format, range is [0, 2]
930  * @param[out] output_val points to output value in Q1.31 format
931  *
932  * @return void
933  */
HAL_CDE_Exp(int8_t input_scale,int32_t input_val,int8_t * output_scale,int32_t * output_val)934 __STATIC_INLINE void HAL_CDE_Exp(int8_t input_scale, int32_t input_val, int8_t *output_scale, int32_t *output_val)
935 {
936     volatile uint64_t result;
937     uint32_t mask;
938 
939     mask = HAL_MATH_DisableInterrupt();
940     result = __arm_cx2da(CP_MATH_CDE, input_scale, input_val,
941                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_EXP, 12));
942     HAL_MATH_EnableInterrupt(mask);
943 
944     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, output_val);
945 
946     return;
947 }
948 
949 /**
950  * @brief  Ln of the given value
951  *         formula: output_val*(2^output_scale)=ln(input_val*(2^input_scale)),
952                     input_val*(2^input_scale) range is (0.107, 9.35)
953  *
954  * @param[in] input_scale input scaling factor in Q8.0 format, range is [0, 4]
955  * @param[in] input_val input value in Q1.31 format
956  * @param[out] output_scale ponits to output scaling factor in Q8.0 format, range is [1, 2]
957  * @param[out] output_val points to output value in Q1.31 format
958  *
959  * @return void
960  */
HAL_CDE_Ln(int8_t input_scale,int32_t input_val,int8_t * output_scale,int32_t * output_val)961 __STATIC_INLINE void HAL_CDE_Ln(int8_t input_scale, int32_t input_val, int8_t *output_scale, int32_t *output_val)
962 {
963     volatile uint64_t result;
964     uint32_t mask;
965 
966     mask = HAL_MATH_DisableInterrupt();
967     result = __arm_cx2da(CP_MATH_CDE, input_scale, input_val,
968                          CP_MATH_CDE_MAKE_CTRL_CODE(CP_MATH_CDE_MODE_LN, 12));
969     HAL_MATH_EnableInterrupt(mask);
970 
971     CP_MATH_GET_SCALE_AND_VAL(result, output_scale, output_val);
972 
973     return;
974 }
975 
976 #endif /* HAL_MATH_CDE_SUPPORT */
977 
978 #ifdef __cplusplus
979 }
980 #endif
981 
982 ///@}   MATH
983 
984 #endif /* __BF0_HAL_MATH_H */