algorithm.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /**
  2. ******************************************************************************
  3. * @file algorithm.c
  4. * @author 张东
  5. * @version V1.0.0
  6. * @date 2019-12-28
  7. * @brief 基础计算算法
  8. ******************************************************************************
  9. */
  10. /*--Include-start-------------------------------------------------------------*/
  11. #include "algorithm.h"
  12. /*base value define-----------------------------------------------------------*/
  13. #define XPI (3.1415926535897932384626433832795)
  14. #define XENTRY (100)
  15. #define XINCL (XPI/2/XENTRY)
  16. #define PI 3.1415926535897932384626433832795028841971 //定义圆周率值
  17. /*Global data space ----------------------------------------------------------*/
  18. //正弦值对应表
  19. static const double XSinTbl[] = {
  20. 0.00000000000000000 , 0.015707317311820675 , 0.031410759078128292 , 0.047106450709642665 , 0.062790519529313374 ,
  21. 0.078459095727844944 , 0.094108313318514325 , 0.10973431109104528 , 0.12533323356430426 , 0.14090123193758267 ,
  22. 0.15643446504023087 , 0.17192910027940955 , 0.18738131458572463 , 0.20278729535651249 , 0.21814324139654256 ,
  23. 0.23344536385590542 , 0.24868988716485479 , 0.26387304996537292 , 0.27899110603922928 , 0.29404032523230400 ,
  24. 0.30901699437494740 , 0.32391741819814940 , 0.33873792024529142 , 0.35347484377925714 , 0.36812455268467797 ,
  25. 0.38268343236508978 , 0.39714789063478062 , 0.41151435860510882 , 0.42577929156507272 , 0.43993916985591514 ,
  26. 0.45399049973954680 , 0.46792981426057340 , 0.48175367410171532 , 0.49545866843240760 , 0.50904141575037132 ,
  27. 0.52249856471594880 , 0.53582679497899666 , 0.54902281799813180 , 0.56208337785213058 , 0.57500525204327857 ,
  28. 0.58778525229247314 , 0.60042022532588402 , 0.61290705365297649 , 0.62524265633570519 , 0.63742398974868975 ,
  29. 0.64944804833018377 , 0.66131186532365183 , 0.67301251350977331 , 0.68454710592868873 , 0.69591279659231442 ,
  30. 0.70710678118654757 , 0.71812629776318881 , 0.72896862742141155 , 0.73963109497860968 , 0.75011106963045959 ,
  31. 0.76040596560003104 , 0.77051324277578925 , 0.78043040733832969 , 0.79015501237569041 , 0.79968465848709058 ,
  32. 0.80901699437494745 , 0.81814971742502351 , 0.82708057427456183 , 0.83580736136827027 , 0.84432792550201508 ,
  33. 0.85264016435409218 , 0.86074202700394364 , 0.86863151443819120 , 0.87630668004386369 , 0.88376563008869347 ,
  34. 0.89100652418836779 , 0.89802757576061565 , 0.90482705246601958 , 0.91140327663544529 , 0.91775462568398114 ,
  35. 0.92387953251128674 , 0.92977648588825146 , 0.93544403082986738 , 0.94088076895422557 , 0.94608535882754530 ,
  36. 0.95105651629515353 , 0.95579301479833012 , 0.96029368567694307 , 0.96455741845779808 , 0.96858316112863108 ,
  37. 0.97236992039767667 , 0.97591676193874743 , 0.97922281062176575 , 0.98228725072868872 , 0.98510932615477398 ,
  38. 0.98768834059513777 , 0.99002365771655754 , 0.99211470131447788 , 0.99396095545517971 , 0.99556196460308000 ,
  39. 0.99691733373312796 , 0.99802672842827156 , 0.99888987496197001 , 0.99950656036573160 , 0.99987663248166059 ,
  40. 1.00000000000000000 };
  41. //向下取整
  42. double my_floor(double x)
  43. {
  44. double y=x;
  45. if( (*( ( (int *) &y)+1) & 0x80000000) != 0) //或者if(x<0)
  46. return (float)((int)x)-1;
  47. else
  48. return (float)((int)x);
  49. }
  50. //求余运算
  51. double my_fmod(double x, double y)
  52. {
  53. double temp, ret;
  54. if (y == 0.0)
  55. return 0.0;
  56. temp = my_floor(x/y);
  57. ret = x - temp * y;
  58. if ((x < 0.0) != (y < 0.0))
  59. ret = ret - y;
  60. return ret;
  61. }
  62. //正弦函数
  63. double XSin( double x )
  64. {
  65. int s = 0 , n;
  66. double dx , sx , cx;
  67. if( x < 0 )
  68. s = 1 , x = -x;
  69. x = my_fmod( x , 2 * XPI );
  70. if( x > XPI )
  71. s = !s , x -= XPI;
  72. if( x > XPI / 2 )
  73. x = XPI - x;
  74. n = (int)( x / XINCL );
  75. dx = x - n * XINCL;
  76. if( dx > XINCL / 2 )
  77. ++n , dx -= XINCL;
  78. sx = XSinTbl[n];
  79. cx = XSinTbl[XENTRY-n];
  80. x = sx + dx*cx - (dx*dx)*sx/2
  81. - (dx*dx*dx)*cx/6
  82. + (dx*dx*dx*dx)*sx/24;
  83. return s ? -x : x;
  84. }
  85. //余弦函数
  86. double XCos( double x )
  87. {
  88. return XSin( x + XPI/2 );
  89. }
  90. //开平方
  91. int qsqrt(int a)
  92. {
  93. uint32_t rem = 0, root = 0, divisor = 0;
  94. uint16_t i;
  95. for(i=0; i<16; i++)
  96. {
  97. root <<= 1;
  98. rem = ((rem << 2) + (a>>30));
  99. a <<= 2;
  100. divisor = (root << 1) + 1;
  101. if(divisor <= rem)
  102. {
  103. rem -= divisor;
  104. root++;
  105. }
  106. }
  107. return root;
  108. }
  109. /*********************************FFT*********************************
  110. 快速傅里叶变换C函数
  111. 函数简介:此函数是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依
  112. 赖硬件。此函数采用联合体的形式表示一个复数,输入为自然顺序的复
  113. 数(输入实数是可令复数虚部为0),输出为经过FFT变换的自然顺序的
  114. 复数
  115. 使用说明:使用此函数只需更改宏定义FFT_N的值即可实现点数的改变,FFT_N的
  116. 应该为2的N次方,不满足此条件时应在后面补0
  117. 函数调用:FFT(s);
  118. 时 间:2010-2-20
  119. 版 本:Ver1.0
  120. 参考文献:
  121. **********************************************************************/
  122. /*******************************************************************
  123. 函数原型:struct compx EE(struct compx b1,struct compx b2)
  124. 函数功能:对两个复数进行乘法运算
  125. 输入参数:两个以联合体定义的复数a,b
  126. 输出参数:a和b的乘积,以联合体的形式输出
  127. *******************************************************************/
  128. struct compx EE(struct compx a,struct compx b)
  129. {
  130. struct compx c;
  131. c.real=a.real*b.real-a.imag*b.imag;
  132. c.imag=a.real*b.imag+a.imag*b.real;
  133. return(c);
  134. }
  135. /*****************************************************************
  136. 函数原型:void FFT(struct compx *xin,int N)
  137. 函数功能:对输入的复数组进行快速傅里叶变换(FFT)
  138. 输入参数:*xin复数结构体组的首地址指针,struct型
  139. *****************************************************************/
  140. void FFT(struct compx *xin)
  141. {
  142. int f,m,nv2,nm1,i,k,l,j=0;
  143. struct compx u,w,t;
  144. nv2=FFT_N/2; //变址运算,即把自然顺序变成倒位序,采用雷德算法
  145. nm1=FFT_N-1;
  146. for(i=0;i<nm1;i++)
  147. {
  148. if(i<j) //如果i<j,即进行变址
  149. {
  150. t=xin[j];
  151. xin[j]=xin[i];
  152. xin[i]=t;
  153. }
  154. k=nv2; //求j的下一个倒位序
  155. while(k<=j) //如果k<=j,表示j的最高位为1
  156. {
  157. j=j-k; //把最高位变成0
  158. k=k/2; //k/2,比较次高位,依次类推,逐个比较,直到某个位为0
  159. }
  160. j=j+k; //把0改为1
  161. }
  162. { //FFT运算核,使用蝶形运算完成FFT运算
  163. int le,lei,ip;
  164. f=FFT_N;
  165. for(l=1;(f=f/2)!=1;l++) //计算l的值,即计算蝶形级数
  166. ;
  167. for(m=1;m<=l;m++) // 控制蝶形结级数
  168. { //m表示第m级蝶形,l为蝶形级总数l=log(2)N
  169. le=2<<(m-1); //le蝶形结距离,即第m级蝶形的蝶形结相距le点
  170. lei=le/2; //同一蝶形结中参加运算的两点的距离
  171. u.real=1.0; //u为蝶形结运算系数,初始值为1
  172. u.imag=0.0;
  173. w.real=XCos(PI/lei); //w为系数商,即当前系数与前一个系数的商
  174. w.imag=-XSin(PI/lei);
  175. for(j=0;j<=lei-1;j++) //控制计算不同种蝶形结,即计算系数不同的蝶形结
  176. {
  177. for(i=j;i<=FFT_N-1;i=i+le) //控制同一蝶形结运算,即计算系数相同蝶形结
  178. {
  179. ip=i+lei; //i,ip分别表示参加蝶形运算的两个节点
  180. t=EE(xin[ip],u); //蝶形运算,详见公式
  181. xin[ip].real=xin[i].real-t.real;
  182. xin[ip].imag=xin[i].imag-t.imag;
  183. xin[i].real=xin[i].real+t.real;
  184. xin[i].imag=xin[i].imag+t.imag;
  185. }
  186. u=EE(u,w); //改变系数,进行下一个蝶形运算
  187. }
  188. }
  189. }
  190. }
  191. //读取峰值
  192. int find_max_num_index(struct compx *data,int count)
  193. {
  194. int i=START_INDEX;
  195. int max_num_index = i;
  196. //struct compx temp=data[i];
  197. float temp = data[i].real;
  198. for(i=START_INDEX;i<count;i++)
  199. {
  200. if(temp < data[i].real)
  201. {
  202. temp = data[i].real;
  203. max_num_index = i;
  204. }
  205. }
  206. //printf("max_num_index=%d\r\n",max_num_index);
  207. return max_num_index;
  208. }
  209. //直流滤波器
  210. int dc_filter(int input,DC_FilterData * df)
  211. {
  212. float new_w = input + df->w * df->a;
  213. int16_t result = 5*(new_w - df->w);
  214. df->w = new_w;
  215. return result;
  216. }
  217. int bw_filter(int input,BW_FilterData * bw) {
  218. bw->v0 = bw->v1;
  219. // v1 = (3.04687470e-2 * input) + (0.9390625058 * v0);
  220. bw->v1 = (1.241106190967544882e-2*input)+(0.97517787618064910582 * bw->v0);
  221. return bw->v0 + bw->v1;
  222. }