You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

373 lines
11 KiB

  1. #include "Pan_Tompkins_detect.h"
  2. /* y(nT) = 1.875y(nT – T) – 0.9219y(nT – 2T) + x (nT) – x(nT – 2T) */
  3. int TwoPoleRecursive(int data)
  4. {
  5. static int xnt, xm1, xm2, ynt, ym1, ym2 = 0;
  6. xnt = data;
  7. ynt = (ym1 + (ym1 >> 1) + (ym1 >> 2) + (ym1 >> 3)) + // 1.875 = 1 + 1/2 + 1/4 + 1/8
  8. (((ym2 >> 1) + (ym2 >> 2) + (ym2 >> 3) + (ym2 >> 5) + (ym2 >> 6)) + xnt - xm2); // 0.916 = 1 + 1/2 + 1/4 + 1/8 + 1/32 + 1/64
  9. xm2 = xm1;
  10. xm1 = xnt;
  11. xm2 = ym1;
  12. ym2 = ym1;
  13. ym1 = ynt;
  14. return ynt;
  15. }
  16. /* y(nT) = 2y(nT – T) – y(nT – 2T) + x(nT) – 2x(nT – 6T) + x(nT – 12T) */
  17. int LowPassFilter(int data)
  18. {
  19. static int y1 = 0, y2 = 0, x[26], n = 12;
  20. int y0;
  21. x[n] = x[n + 13] = data;
  22. y0 = (y1 << 1) - y2 + x[n] - (x[n + 6] << 1) + x[n + 12];
  23. y2 = y1;
  24. y1 = y0;
  25. y0 >>= 5;
  26. if(--n < 0){
  27. n = 12;
  28. }
  29. return y0;
  30. }
  31. /* p(nT) = x(nT – 16T) – 32 [y(nT – T) + x(nT) – x(nT – 32T)] */
  32. int HighPassFilter(int data)
  33. {
  34. static int y1 = 0, x[66], n = 32;
  35. int y0;
  36. x[n] = x[n + 33] = data;
  37. y0 = y1 + x[n] - x[n + 32];
  38. y1 = y0;
  39. if(--n < 0){
  40. n = 32;
  41. }
  42. return (x[n + 16] - (y0 >> 5));
  43. }
  44. /* y = 1/8 (2x( nT) + x( nT - T) - x( nT - 3T) - 2x( nT - 4T)) */
  45. int Derivative(int data)
  46. {
  47. int y;
  48. static int x_derv[4];
  49. y = (data << 1) + x_derv[3] - x_derv[1] - ( x_derv[0] << 1);
  50. y >>= 3;
  51. for(int i = 0; i < 3; ++i){
  52. x_derv[i] = x_derv[i + 1];
  53. }
  54. x_derv[3] = data;
  55. return y;
  56. }
  57. int Squar(int data)
  58. {
  59. return (data * data);
  60. }
  61. /* y(nT) = 1/N [x(nT – (N – 1)T) + x(nT – (N – 2)T) +...+ x(nT)] */
  62. int MovingWindowIntegral(int data)
  63. {
  64. //static const int WINDOW_SIZE = SAMPLING_RATE * 0.2;
  65. #define WINDOW_SIZE 72
  66. static int x[WINDOW_SIZE], ptr = 0;
  67. static long sum = 0;
  68. long ly;
  69. int y;
  70. if(++ptr == WINDOW_SIZE){
  71. ptr = 0;
  72. }
  73. sum -= x[ptr];
  74. sum += data;
  75. x[ptr] = data;
  76. ly = sum >> 5;
  77. uint32_t MAX_INTEGRAL = 4096;//32400;
  78. if(ly > MAX_INTEGRAL){
  79. y = MAX_INTEGRAL;
  80. }
  81. else{
  82. y = (int)ly;
  83. }
  84. return (y);
  85. }
  86. SignalPoint ThresholdCalculate(int sample,float value,int bandpass,int square,int integral)
  87. {
  88. //static const int QRS_TIME = SAMPLING_RATE * 0.1;
  89. //static const int SEARCH_BACK_TIME = SAMPLING_RATE * 1.66f;
  90. #define QRS_TIME 36
  91. #define SEARCH_BACK_TIME 598
  92. static int bandpass_buffer[SEARCH_BACK_TIME],integral_buffer[SEARCH_BACK_TIME];
  93. static SignalPoint peak_buffer[SEARCH_BACK_TIME];
  94. static int square_buffer[QRS_TIME];
  95. static long unsigned last_qrs = 0, last_slope = 0, current_slope = 0;
  96. static int peak_i = 0, peak_f = 0, threshold_i1 = 0, threshold_i2 = 0, threshold_f1 = 0, threshold_f2 = 0, spk_i = 0, spk_f = 0, npk_i = 0, npk_f = 0;
  97. static bool qrs, regular = true, prev_regular;
  98. static int rr1[8]={0}, rr2[8]={0}, rravg1, rravg2, rrlow = 0, rrhigh = 0, rrmiss = 0;
  99. SignalPoint result;
  100. result.index = -1;
  101. peak_buffer[sample%SEARCH_BACK_TIME].index = sample;
  102. peak_buffer[sample%SEARCH_BACK_TIME].value = value;
  103. bandpass_buffer[sample%SEARCH_BACK_TIME] = bandpass;
  104. integral_buffer[sample%SEARCH_BACK_TIME] = integral;
  105. square_buffer[sample%QRS_TIME] = square;
  106. // If the current signal is above one of the thresholds (integral or filtered signal), it's a peak candidate.
  107. if(integral >= threshold_i1 || bandpass >= threshold_f1){
  108. peak_i = integral;
  109. peak_f = bandpass;
  110. }
  111. // If both the integral and the signal are above their thresholds, they're probably signal peaks.
  112. if((integral >= threshold_i1) && (bandpass >= threshold_f1)){
  113. // There's a 200ms latency. If the new peak respects this condition, we can keep testing.
  114. if(sample > last_qrs + SAMPLING_RATE*0.2f){
  115. //if(sample > last_qrs + (SAMPLING_RATE*0.2f)){
  116. // If it respects the 200ms latency, but it doesn't respect the 360ms latency, we check the slope.
  117. if(sample <= last_qrs + (long unsigned int)(0.36*SAMPLING_RATE)){
  118. // The squared slope is "M" shaped. So we have to check nearby samples to make sure we're really looking
  119. // at its peak value, rather than a low one.
  120. int current = sample;
  121. current_slope = 0;
  122. for(int j = current - QRS_TIME; j <= current; ++j){
  123. if(square_buffer[j%QRS_TIME] > current_slope){
  124. current_slope = square_buffer[j%QRS_TIME];
  125. }
  126. }
  127. //current_slope = square;
  128. if(current_slope <= (int)(last_slope/2)){
  129. qrs = false;
  130. //return qrs;
  131. }
  132. else{
  133. spk_i = 0.125*peak_i + 0.875*spk_i;
  134. threshold_i1 = npk_i + 0.25*(spk_i - npk_i);
  135. threshold_i2 = 0.5*threshold_i1;
  136. spk_f = 0.125*peak_f + 0.875*spk_f;
  137. threshold_f1 = npk_f + 0.25*(spk_f - npk_f);
  138. threshold_f2 = 0.5*threshold_f1;
  139. last_slope = current_slope;
  140. qrs = true;
  141. result.value = value;
  142. result.index = sample;
  143. }
  144. }
  145. // If it was above both thresholds and respects both latency periods, it certainly is a R peak.
  146. else{
  147. int current = sample;
  148. current_slope = 0;
  149. for(int j = current - QRS_TIME; j <= current; ++j){
  150. if(square_buffer[j%QRS_TIME] > current_slope){
  151. current_slope = square_buffer[j%QRS_TIME];
  152. }
  153. }
  154. //current_slope = square;
  155. spk_i = 0.125*peak_i + 0.875*spk_i;
  156. threshold_i1 = npk_i + 0.25*(spk_i - npk_i);
  157. threshold_i2 = 0.5*threshold_i1;
  158. spk_f = 0.125*peak_f + 0.875*spk_f;
  159. threshold_f1 = npk_f + 0.25*(spk_f - npk_f);
  160. threshold_f2 = 0.5*threshold_f1;
  161. last_slope = current_slope;
  162. qrs = true;
  163. result.value = value;
  164. result.index = sample;
  165. }
  166. }
  167. // If the new peak doesn't respect the 200ms latency, it's noise. Update thresholds and move on to the next sample.
  168. else{
  169. peak_i = integral;
  170. npk_i = 0.125*peak_i + 0.875*npk_i;
  171. threshold_i1 = npk_i + 0.25*(spk_i - npk_i);
  172. threshold_i2 = 0.5*threshold_i1;
  173. peak_f = bandpass;
  174. npk_f = 0.125*peak_f + 0.875*npk_f;
  175. threshold_f1 = npk_f + 0.25*(spk_f - npk_f);
  176. threshold_f2 = 0.5*threshold_f1;
  177. qrs = false;
  178. /*outputSignal[current] = qrs;
  179. if (sample > DELAY + BUFFSIZE)
  180. output(outputSignal[0]);
  181. continue;*/
  182. //return qrs;
  183. return result;
  184. }
  185. }
  186. // If a QRS complex was detected, the RR-averages must be updated.
  187. if(qrs){
  188. // Add the newest RR-interval to the buffer and get the new average.
  189. rravg1 = 0;
  190. for (int i = 0; i < 7; ++i){
  191. rr1[i] = rr1[i+1];
  192. rravg1 += rr1[i];
  193. }
  194. rr1[7] = sample - last_qrs;
  195. last_qrs = sample;
  196. rravg1 += rr1[7];
  197. rravg1 *= 0.125;
  198. // If the newly-discovered RR-average is normal, add it to the "normal" buffer and get the new "normal" average.
  199. // Update the "normal" beat parameters.
  200. if ( (rr1[7] >= rrlow) && (rr1[7] <= rrhigh) ){
  201. rravg2 = 0;
  202. for (int i = 0; i < 7; ++i){
  203. rr2[i] = rr2[i+1];
  204. rravg2 += rr2[i];
  205. }
  206. rr2[7] = rr1[7];
  207. rravg2 += rr2[7];
  208. rravg2 *= 0.125;
  209. rrlow = 0.92*rravg2;
  210. rrhigh = 1.16*rravg2;
  211. rrmiss = 1.66*rravg2;
  212. }
  213. prev_regular = regular;
  214. if(rravg1 == rravg2){
  215. regular = true;
  216. }
  217. // If the beat had been normal but turned odd, change the thresholds.
  218. else{
  219. regular = false;
  220. if (prev_regular){
  221. threshold_i1 /= 2;
  222. threshold_f1 /= 2;
  223. }
  224. }
  225. }
  226. // If no R-peak was detected, it's important to check how long it's been since the last detection.
  227. else{
  228. int current = sample;
  229. // If no R-peak was detected for too long, use the lighter thresholds and do a back search.
  230. // However, the back search must respect the 200ms limit and the 360ms one (check the slope).
  231. if((sample - last_qrs > (long unsigned int)rrmiss) && (sample > last_qrs + SAMPLING_RATE*0.2f)){
  232. //if((sample - last_qrs > (long unsigned int)rrmiss) && (sample > last_qrs + (SAMPLING_RATE*0.2f))){
  233. // If over SEARCH_BACK_TIME of QRS complex
  234. if((sample - last_qrs) > SEARCH_BACK_TIME){
  235. last_qrs = sample;
  236. //return result;
  237. }
  238. int qrs_last_index = 0; // Last point of QRS complex
  239. for(int i = current - (sample - last_qrs) + SAMPLING_RATE*0.2f; i < (long unsigned int)current; ++i){
  240. //for(int i = current - (sample - last_qrs) + (SAMPLING_RATE*0.2f); i < (long unsigned int)current; ++i){
  241. if((integral_buffer[i%SEARCH_BACK_TIME] > threshold_i2) && (bandpass_buffer[i%SEARCH_BACK_TIME] > threshold_f2)){
  242. current_slope = 0;
  243. for(int j = current - QRS_TIME; j <= current; ++j){
  244. if(square_buffer[j%QRS_TIME] > current_slope){
  245. current_slope = square_buffer[j%QRS_TIME];
  246. }
  247. }
  248. //current_slope = square;
  249. if((current_slope < (int)(last_slope/2)) && (i + sample) < last_qrs + 0.36*last_qrs){
  250. qrs = false;
  251. }
  252. else if(i - last_qrs > 550){
  253. peak_i = integral_buffer[i%SEARCH_BACK_TIME];
  254. peak_f = bandpass_buffer[i%SEARCH_BACK_TIME];
  255. spk_i = 0.25*peak_i+ 0.75*spk_i;
  256. spk_f = 0.25*peak_f + 0.75*spk_f;
  257. threshold_i1 = npk_i + 0.25*(spk_i - npk_i);
  258. threshold_i2 = 0.5*threshold_i1;
  259. last_slope = current_slope;
  260. threshold_f1 = npk_f + 0.25*(spk_f - npk_f);
  261. threshold_f2 = 0.5*threshold_f1;
  262. // If a signal peak was detected on the back search, the RR attributes must be updated.
  263. // This is the same thing done when a peak is detected on the first try.
  264. //RR Average 1
  265. rravg1 = 0;
  266. for(int j = 0; j < 7; ++j){
  267. rr1[j] = rr1[j+1];
  268. rravg1 += rr1[j];
  269. }
  270. rr1[7] = sample - (current - i) - last_qrs;
  271. qrs = true;
  272. qrs_last_index = i;
  273. last_qrs = sample - (current - i);
  274. rravg1 += rr1[7];
  275. rravg1 *= 0.125;
  276. //RR Average 2
  277. if((rr1[7] >= rrlow) && (rr1[7] <= rrhigh)){
  278. rravg2 = 0;
  279. for (int i = 0; i < 7; ++i){
  280. rr2[i] = rr2[i+1];
  281. rravg2 += rr2[i];
  282. }
  283. rr2[7] = rr1[7];
  284. rravg2 += rr2[7];
  285. rravg2 *= 0.125;
  286. rrlow = 0.92*rravg2;
  287. rrhigh = 1.16*rravg2;
  288. rrmiss = 1.66*rravg2;
  289. }
  290. prev_regular = regular;
  291. if(rravg1 == rravg2){
  292. regular = true;
  293. }
  294. else{
  295. regular = false;
  296. if(prev_regular){
  297. threshold_i1 /= 2;
  298. threshold_f1 /= 2;
  299. }
  300. }
  301. break;
  302. }
  303. }
  304. }
  305. if(qrs){
  306. //outputSignal[current] = false;
  307. //outputSignal[i] = true;
  308. //if (sample > DELAY + BUFFSIZE)
  309. //output(outputSignal[0]);
  310. //continue;
  311. //return qrs;
  312. return peak_buffer[qrs_last_index%SEARCH_BACK_TIME];
  313. }
  314. }
  315. // Definitely no signal peak was detected.
  316. if(!qrs){
  317. // If some kind of peak had been detected, then it's certainly a noise peak. Thresholds must be updated accordinly.
  318. if((integral >= threshold_i1) || (bandpass >= threshold_f1)){
  319. peak_i = integral;
  320. npk_i = 0.125*peak_i + 0.875*npk_i;
  321. threshold_i1 = npk_i + 0.25*(spk_i - npk_i);
  322. threshold_i2 = 0.5*threshold_i1;
  323. peak_f = bandpass;
  324. npk_f = 0.125*peak_f + 0.875*npk_f;
  325. threshold_f1 = npk_f + 0.25*(spk_f - npk_f);
  326. threshold_f2 = 0.5*threshold_f1;
  327. }
  328. }
  329. }
  330. return result;
  331. }