I've got some basic filter code setup (but not yet tested).

Dependencies:   BLE_API Queue mbed nRF51822

Fork of BLE_HeartRate by Bluetooth Low Energy

Committer:
roysandberg
Date:
Sun Jun 28 03:06:00 2015 +0000
Revision:
62:8e2fbe131b53
Working Beat Detection and Analysis

Who changed what in which revision?

UserRevisionLine numberNew contents of line
roysandberg 62:8e2fbe131b53 1 /*****************************************************************************
roysandberg 62:8e2fbe131b53 2 FILE: analbeat.cpp
roysandberg 62:8e2fbe131b53 3 AUTHOR: Patrick S. Hamilton
roysandberg 62:8e2fbe131b53 4 REVISED: 5/13/2002
roysandberg 62:8e2fbe131b53 5 ___________________________________________________________________________
roysandberg 62:8e2fbe131b53 6
roysandberg 62:8e2fbe131b53 7 analbeat.cpp: Analyze Beat
roysandberg 62:8e2fbe131b53 8 Copywrite (C) 2001 Patrick S. Hamilton
roysandberg 62:8e2fbe131b53 9
roysandberg 62:8e2fbe131b53 10 This file is free software; you can redistribute it and/or modify it under
roysandberg 62:8e2fbe131b53 11 the terms of the GNU Library General Public License as published by the Free
roysandberg 62:8e2fbe131b53 12 Software Foundation; either version 2 of the License, or (at your option) any
roysandberg 62:8e2fbe131b53 13 later version.
roysandberg 62:8e2fbe131b53 14
roysandberg 62:8e2fbe131b53 15 This software is distributed in the hope that it will be useful, but WITHOUT ANY
roysandberg 62:8e2fbe131b53 16 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
roysandberg 62:8e2fbe131b53 17 PARTICULAR PURPOSE. See the GNU Library General Public License for more
roysandberg 62:8e2fbe131b53 18 details.
roysandberg 62:8e2fbe131b53 19
roysandberg 62:8e2fbe131b53 20 You should have received a copy of the GNU Library General Public License along
roysandberg 62:8e2fbe131b53 21 with this library; if not, write to the Free Software Foundation, Inc., 59
roysandberg 62:8e2fbe131b53 22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
roysandberg 62:8e2fbe131b53 23
roysandberg 62:8e2fbe131b53 24 You may contact the author by e-mail (pat@eplimited.edu) or postal mail
roysandberg 62:8e2fbe131b53 25 (Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
roysandberg 62:8e2fbe131b53 26 MA 02143 USA). For updates to this software, please visit our website
roysandberg 62:8e2fbe131b53 27 (http://www.eplimited.com).
roysandberg 62:8e2fbe131b53 28 __________________________________________________________________________
roysandberg 62:8e2fbe131b53 29
roysandberg 62:8e2fbe131b53 30 This file contains functions for determining the QRS onset, QRS offset,
roysandberg 62:8e2fbe131b53 31 beat onset, beat offset, polarity, and isoelectric level for a beat.
roysandberg 62:8e2fbe131b53 32
roysandberg 62:8e2fbe131b53 33 Revisions:
roysandberg 62:8e2fbe131b53 34 4/16: Modified to prevent isoStart from being set to less than ISO_LENGTH1-1
roysandberg 62:8e2fbe131b53 35 5/13/2002: Time related constants are tied to BEAT_SAMPLE_RATE in bdac.h.
roysandberg 62:8e2fbe131b53 36
roysandberg 62:8e2fbe131b53 37 *****************************************************************************/
roysandberg 62:8e2fbe131b53 38 #include <mbed.h>
roysandberg 62:8e2fbe131b53 39 #include "bdac.h"
roysandberg 62:8e2fbe131b53 40 //#include <stdio.h>
roysandberg 62:8e2fbe131b53 41 //#include <stdlib.h>
roysandberg 62:8e2fbe131b53 42
roysandberg 62:8e2fbe131b53 43 #define ISO_LENGTH1 BEAT_MS50
roysandberg 62:8e2fbe131b53 44 #define ISO_LENGTH2 BEAT_MS80
roysandberg 62:8e2fbe131b53 45 #define ISO_LIMIT 20
roysandberg 62:8e2fbe131b53 46
roysandberg 62:8e2fbe131b53 47 // Local prototypes.
roysandberg 62:8e2fbe131b53 48
roysandberg 62:8e2fbe131b53 49 int IsoCheck(int *data, int isoLength);
roysandberg 62:8e2fbe131b53 50
roysandberg 62:8e2fbe131b53 51 /****************************************************************
roysandberg 62:8e2fbe131b53 52 IsoCheck determines whether the amplitudes of a run
roysandberg 62:8e2fbe131b53 53 of data fall within a sufficiently small amplitude that
roysandberg 62:8e2fbe131b53 54 the run can be considered isoelectric.
roysandberg 62:8e2fbe131b53 55 *****************************************************************/
roysandberg 62:8e2fbe131b53 56
roysandberg 62:8e2fbe131b53 57 int IsoCheck(int *data, int isoLength)
roysandberg 62:8e2fbe131b53 58 {
roysandberg 62:8e2fbe131b53 59 int i, max, min ;
roysandberg 62:8e2fbe131b53 60
roysandberg 62:8e2fbe131b53 61 for(i = 1, max=min = data[0]; i < isoLength; ++i)
roysandberg 62:8e2fbe131b53 62 {
roysandberg 62:8e2fbe131b53 63 if(data[i] > max)
roysandberg 62:8e2fbe131b53 64 max = data[i] ;
roysandberg 62:8e2fbe131b53 65 else if(data[i] < min)
roysandberg 62:8e2fbe131b53 66 min = data[i] ;
roysandberg 62:8e2fbe131b53 67 }
roysandberg 62:8e2fbe131b53 68
roysandberg 62:8e2fbe131b53 69 if(max - min < ISO_LIMIT)
roysandberg 62:8e2fbe131b53 70 return(1) ;
roysandberg 62:8e2fbe131b53 71 return(0) ;
roysandberg 62:8e2fbe131b53 72 }
roysandberg 62:8e2fbe131b53 73
roysandberg 62:8e2fbe131b53 74 /**********************************************************************
roysandberg 62:8e2fbe131b53 75 AnalyzeBeat takes a beat buffer as input and returns (via pointers)
roysandberg 62:8e2fbe131b53 76 estimates of the QRS onset, QRS offset, polarity, isoelectric level
roysandberg 62:8e2fbe131b53 77 beat beginning (P-wave onset), and beat ending (T-wave offset).
roysandberg 62:8e2fbe131b53 78 Analyze Beat assumes that the beat has been sampled at 100 Hz, is
roysandberg 62:8e2fbe131b53 79 BEATLGTH long, and has an R-wave location of roughly FIDMARK.
roysandberg 62:8e2fbe131b53 80
roysandberg 62:8e2fbe131b53 81 Note that beatBegin is the number of samples before FIDMARK that
roysandberg 62:8e2fbe131b53 82 the beat begins and beatEnd is the number of samples after the
roysandberg 62:8e2fbe131b53 83 FIDMARK that the beat ends.
roysandberg 62:8e2fbe131b53 84 ************************************************************************/
roysandberg 62:8e2fbe131b53 85
roysandberg 62:8e2fbe131b53 86 #define INF_CHK_N BEAT_MS40
roysandberg 62:8e2fbe131b53 87
roysandberg 62:8e2fbe131b53 88 void AnalyzeBeat(int *beat, int *onset, int *offset, int *isoLevel,
roysandberg 62:8e2fbe131b53 89 int *beatBegin, int *beatEnd, int *amp)
roysandberg 62:8e2fbe131b53 90 {
roysandberg 62:8e2fbe131b53 91 int maxSlope = 0, maxSlopeI, minSlope = 0, minSlopeI ;
roysandberg 62:8e2fbe131b53 92 int maxV, minV ;
roysandberg 62:8e2fbe131b53 93 int isoStart, isoEnd ;
roysandberg 62:8e2fbe131b53 94 int slope, i ;
roysandberg 62:8e2fbe131b53 95
roysandberg 62:8e2fbe131b53 96 // Search back from the fiducial mark to find the isoelectric
roysandberg 62:8e2fbe131b53 97 // region preceeding the QRS complex.
roysandberg 62:8e2fbe131b53 98
roysandberg 62:8e2fbe131b53 99 for(i = FIDMARK-ISO_LENGTH2; (i > 0) && (IsoCheck(&beat[i],ISO_LENGTH2) == 0); --i) ;
roysandberg 62:8e2fbe131b53 100
roysandberg 62:8e2fbe131b53 101 // If the first search didn't turn up any isoelectric region, look for
roysandberg 62:8e2fbe131b53 102 // a shorter isoelectric region.
roysandberg 62:8e2fbe131b53 103
roysandberg 62:8e2fbe131b53 104 if(i == 0)
roysandberg 62:8e2fbe131b53 105 {
roysandberg 62:8e2fbe131b53 106 for(i = FIDMARK-ISO_LENGTH1; (i > 0) && (IsoCheck(&beat[i],ISO_LENGTH1) == 0); --i) ;
roysandberg 62:8e2fbe131b53 107 isoStart = i + (ISO_LENGTH1 - 1) ;
roysandberg 62:8e2fbe131b53 108 }
roysandberg 62:8e2fbe131b53 109 else isoStart = i + (ISO_LENGTH2 - 1) ;
roysandberg 62:8e2fbe131b53 110
roysandberg 62:8e2fbe131b53 111 // Search forward from the R-wave to find an isoelectric region following
roysandberg 62:8e2fbe131b53 112 // the QRS complex.
roysandberg 62:8e2fbe131b53 113
roysandberg 62:8e2fbe131b53 114 for(i = FIDMARK; (i < BEATLGTH) && (IsoCheck(&beat[i],ISO_LENGTH1) == 0); ++i) ;
roysandberg 62:8e2fbe131b53 115 isoEnd = i ;
roysandberg 62:8e2fbe131b53 116
roysandberg 62:8e2fbe131b53 117 // Find the maximum and minimum slopes on the
roysandberg 62:8e2fbe131b53 118 // QRS complex.
roysandberg 62:8e2fbe131b53 119
roysandberg 62:8e2fbe131b53 120 i = FIDMARK-BEAT_MS150 ;
roysandberg 62:8e2fbe131b53 121 maxSlope = maxSlope = beat[i] - beat[i-1] ;
roysandberg 62:8e2fbe131b53 122 maxSlopeI = minSlopeI = i ;
roysandberg 62:8e2fbe131b53 123
roysandberg 62:8e2fbe131b53 124 for(; i < FIDMARK+BEAT_MS150; ++i)
roysandberg 62:8e2fbe131b53 125 {
roysandberg 62:8e2fbe131b53 126 slope = beat[i] - beat[i-1] ;
roysandberg 62:8e2fbe131b53 127 if(slope > maxSlope)
roysandberg 62:8e2fbe131b53 128 {
roysandberg 62:8e2fbe131b53 129 maxSlope = slope ;
roysandberg 62:8e2fbe131b53 130 maxSlopeI = i ;
roysandberg 62:8e2fbe131b53 131 }
roysandberg 62:8e2fbe131b53 132 else if(slope < minSlope)
roysandberg 62:8e2fbe131b53 133 {
roysandberg 62:8e2fbe131b53 134 minSlope = slope ;
roysandberg 62:8e2fbe131b53 135 minSlopeI = i ;
roysandberg 62:8e2fbe131b53 136 }
roysandberg 62:8e2fbe131b53 137 }
roysandberg 62:8e2fbe131b53 138
roysandberg 62:8e2fbe131b53 139 // Use the smallest of max or min slope for search parameters.
roysandberg 62:8e2fbe131b53 140
roysandberg 62:8e2fbe131b53 141 if(maxSlope > -minSlope)
roysandberg 62:8e2fbe131b53 142 maxSlope = -minSlope ;
roysandberg 62:8e2fbe131b53 143 else minSlope = -maxSlope ;
roysandberg 62:8e2fbe131b53 144
roysandberg 62:8e2fbe131b53 145 if(maxSlopeI < minSlopeI)
roysandberg 62:8e2fbe131b53 146 {
roysandberg 62:8e2fbe131b53 147
roysandberg 62:8e2fbe131b53 148 // Search back from the maximum slope point for the QRS onset.
roysandberg 62:8e2fbe131b53 149
roysandberg 62:8e2fbe131b53 150 for(i = maxSlopeI;
roysandberg 62:8e2fbe131b53 151 (i > 0) && ((beat[i]-beat[i-1]) > (maxSlope >> 2)); --i) ;
roysandberg 62:8e2fbe131b53 152 *onset = i-1 ;
roysandberg 62:8e2fbe131b53 153
roysandberg 62:8e2fbe131b53 154 // Check to see if this was just a brief inflection.
roysandberg 62:8e2fbe131b53 155
roysandberg 62:8e2fbe131b53 156 for(; (i > *onset-INF_CHK_N) && ((beat[i]-beat[i-1]) <= (maxSlope >>2)); --i) ;
roysandberg 62:8e2fbe131b53 157 if(i > *onset-INF_CHK_N)
roysandberg 62:8e2fbe131b53 158 {
roysandberg 62:8e2fbe131b53 159 for(;(i > 0) && ((beat[i]-beat[i-1]) > (maxSlope >> 2)); --i) ;
roysandberg 62:8e2fbe131b53 160 *onset = i-1 ;
roysandberg 62:8e2fbe131b53 161 }
roysandberg 62:8e2fbe131b53 162 i = *onset+1 ;
roysandberg 62:8e2fbe131b53 163
roysandberg 62:8e2fbe131b53 164 // Check to see if a large negative slope follows an inflection.
roysandberg 62:8e2fbe131b53 165 // If so, extend the onset a little more.
roysandberg 62:8e2fbe131b53 166
roysandberg 62:8e2fbe131b53 167 for(;(i > *onset-INF_CHK_N) && ((beat[i-1]-beat[i]) < (maxSlope>>2)); --i);
roysandberg 62:8e2fbe131b53 168 if(i > *onset-INF_CHK_N)
roysandberg 62:8e2fbe131b53 169 {
roysandberg 62:8e2fbe131b53 170 for(; (i > 0) && ((beat[i-1]-beat[i]) > (maxSlope>>2)); --i) ;
roysandberg 62:8e2fbe131b53 171 *onset = i-1 ;
roysandberg 62:8e2fbe131b53 172 }
roysandberg 62:8e2fbe131b53 173
roysandberg 62:8e2fbe131b53 174 // Search forward from minimum slope point for QRS offset.
roysandberg 62:8e2fbe131b53 175
roysandberg 62:8e2fbe131b53 176 for(i = minSlopeI;
roysandberg 62:8e2fbe131b53 177 (i < BEATLGTH) && ((beat[i] - beat[i-1]) < (minSlope >>2)); ++i);
roysandberg 62:8e2fbe131b53 178 *offset = i ;
roysandberg 62:8e2fbe131b53 179
roysandberg 62:8e2fbe131b53 180 // Make sure this wasn't just an inflection.
roysandberg 62:8e2fbe131b53 181
roysandberg 62:8e2fbe131b53 182 for(; (i < *offset+INF_CHK_N) && ((beat[i]-beat[i-1]) >= (minSlope>>2)); ++i) ;
roysandberg 62:8e2fbe131b53 183 if(i < *offset+INF_CHK_N)
roysandberg 62:8e2fbe131b53 184 {
roysandberg 62:8e2fbe131b53 185 for(;(i < BEATLGTH) && ((beat[i]-beat[i-1]) < (minSlope >>2)); ++i) ;
roysandberg 62:8e2fbe131b53 186 *offset = i ;
roysandberg 62:8e2fbe131b53 187 }
roysandberg 62:8e2fbe131b53 188 i = *offset ;
roysandberg 62:8e2fbe131b53 189
roysandberg 62:8e2fbe131b53 190 // Check to see if there is a significant upslope following
roysandberg 62:8e2fbe131b53 191 // the end of the down slope.
roysandberg 62:8e2fbe131b53 192
roysandberg 62:8e2fbe131b53 193 for(;(i < *offset+BEAT_MS40) && ((beat[i-1]-beat[i]) > (minSlope>>2)); ++i);
roysandberg 62:8e2fbe131b53 194 if(i < *offset+BEAT_MS40)
roysandberg 62:8e2fbe131b53 195 {
roysandberg 62:8e2fbe131b53 196 for(; (i < BEATLGTH) && ((beat[i-1]-beat[i]) < (minSlope>>2)); ++i) ;
roysandberg 62:8e2fbe131b53 197 *offset = i ;
roysandberg 62:8e2fbe131b53 198
roysandberg 62:8e2fbe131b53 199 // One more search motivated by PVC shape in 123.
roysandberg 62:8e2fbe131b53 200
roysandberg 62:8e2fbe131b53 201 for(; (i < *offset+BEAT_MS60) && (beat[i]-beat[i-1] > (minSlope>>2)); ++i) ;
roysandberg 62:8e2fbe131b53 202 if(i < *offset + BEAT_MS60)
roysandberg 62:8e2fbe131b53 203 {
roysandberg 62:8e2fbe131b53 204 for(;(i < BEATLGTH) && (beat[i]-beat[i-1] < (minSlope>>2)); ++i) ;
roysandberg 62:8e2fbe131b53 205 *offset = i ;
roysandberg 62:8e2fbe131b53 206 }
roysandberg 62:8e2fbe131b53 207 }
roysandberg 62:8e2fbe131b53 208 }
roysandberg 62:8e2fbe131b53 209
roysandberg 62:8e2fbe131b53 210 else
roysandberg 62:8e2fbe131b53 211 {
roysandberg 62:8e2fbe131b53 212
roysandberg 62:8e2fbe131b53 213 // Search back from the minimum slope point for the QRS onset.
roysandberg 62:8e2fbe131b53 214
roysandberg 62:8e2fbe131b53 215 for(i = minSlopeI;
roysandberg 62:8e2fbe131b53 216 (i > 0) && ((beat[i]-beat[i-1]) < (minSlope >> 2)); --i) ;
roysandberg 62:8e2fbe131b53 217 *onset = i-1 ;
roysandberg 62:8e2fbe131b53 218
roysandberg 62:8e2fbe131b53 219 // Check to see if this was just a brief inflection.
roysandberg 62:8e2fbe131b53 220
roysandberg 62:8e2fbe131b53 221 for(; (i > *onset-INF_CHK_N) && ((beat[i]-beat[i-1]) >= (minSlope>>2)); --i) ;
roysandberg 62:8e2fbe131b53 222 if(i > *onset-INF_CHK_N)
roysandberg 62:8e2fbe131b53 223 {
roysandberg 62:8e2fbe131b53 224 for(; (i > 0) && ((beat[i]-beat[i-1]) < (minSlope>>2));--i) ;
roysandberg 62:8e2fbe131b53 225 *onset = i-1 ;
roysandberg 62:8e2fbe131b53 226 }
roysandberg 62:8e2fbe131b53 227 i = *onset+1 ;
roysandberg 62:8e2fbe131b53 228
roysandberg 62:8e2fbe131b53 229 // Check for significant positive slope after a turning point.
roysandberg 62:8e2fbe131b53 230
roysandberg 62:8e2fbe131b53 231 for(;(i > *onset-INF_CHK_N) && ((beat[i-1]-beat[i]) > (minSlope>>2)); --i);
roysandberg 62:8e2fbe131b53 232 if(i > *onset-INF_CHK_N)
roysandberg 62:8e2fbe131b53 233 {
roysandberg 62:8e2fbe131b53 234 for(; (i > 0) && ((beat[i-1]-beat[i]) < (minSlope>>2)); --i) ;
roysandberg 62:8e2fbe131b53 235 *onset = i-1 ;
roysandberg 62:8e2fbe131b53 236 }
roysandberg 62:8e2fbe131b53 237
roysandberg 62:8e2fbe131b53 238 // Search forward from maximum slope point for QRS offset.
roysandberg 62:8e2fbe131b53 239
roysandberg 62:8e2fbe131b53 240 for(i = maxSlopeI;
roysandberg 62:8e2fbe131b53 241 (i < BEATLGTH) && ((beat[i] - beat[i-1]) > (maxSlope >>2)); ++i) ;
roysandberg 62:8e2fbe131b53 242 *offset = i ;
roysandberg 62:8e2fbe131b53 243
roysandberg 62:8e2fbe131b53 244 // Check to see if this was just a brief inflection.
roysandberg 62:8e2fbe131b53 245
roysandberg 62:8e2fbe131b53 246 for(; (i < *offset+INF_CHK_N) && ((beat[i] - beat[i-1]) <= (maxSlope >> 2)); ++i) ;
roysandberg 62:8e2fbe131b53 247 if(i < *offset+INF_CHK_N)
roysandberg 62:8e2fbe131b53 248 {
roysandberg 62:8e2fbe131b53 249 for(;(i < BEATLGTH) && ((beat[i] - beat[i-1]) > (maxSlope >>2)); ++i) ;
roysandberg 62:8e2fbe131b53 250 *offset = i ;
roysandberg 62:8e2fbe131b53 251 }
roysandberg 62:8e2fbe131b53 252 i = *offset ;
roysandberg 62:8e2fbe131b53 253
roysandberg 62:8e2fbe131b53 254 // Check to see if there is a significant downslope following
roysandberg 62:8e2fbe131b53 255 // the end of the up slope.
roysandberg 62:8e2fbe131b53 256
roysandberg 62:8e2fbe131b53 257 for(;(i < *offset+BEAT_MS40) && ((beat[i-1]-beat[i]) < (maxSlope>>2)); ++i);
roysandberg 62:8e2fbe131b53 258 if(i < *offset+BEAT_MS40)
roysandberg 62:8e2fbe131b53 259 {
roysandberg 62:8e2fbe131b53 260 for(; (i < BEATLGTH) && ((beat[i-1]-beat[i]) > (maxSlope>>2)); ++i) ;
roysandberg 62:8e2fbe131b53 261 *offset = i ;
roysandberg 62:8e2fbe131b53 262 }
roysandberg 62:8e2fbe131b53 263 }
roysandberg 62:8e2fbe131b53 264
roysandberg 62:8e2fbe131b53 265 // If the estimate of the beginning of the isoelectric level was
roysandberg 62:8e2fbe131b53 266 // at the beginning of the beat, use the slope based QRS onset point
roysandberg 62:8e2fbe131b53 267 // as the iso electric point.
roysandberg 62:8e2fbe131b53 268
roysandberg 62:8e2fbe131b53 269 if((isoStart == ISO_LENGTH1-1)&& (*onset > isoStart)) // ** 4/19 **
roysandberg 62:8e2fbe131b53 270 isoStart = *onset ;
roysandberg 62:8e2fbe131b53 271
roysandberg 62:8e2fbe131b53 272 // Otherwise, if the isoelectric start and the slope based points
roysandberg 62:8e2fbe131b53 273 // are close, use the isoelectric start point.
roysandberg 62:8e2fbe131b53 274
roysandberg 62:8e2fbe131b53 275 else if(*onset-isoStart < BEAT_MS50)
roysandberg 62:8e2fbe131b53 276 *onset = isoStart ;
roysandberg 62:8e2fbe131b53 277
roysandberg 62:8e2fbe131b53 278 // If the isoelectric end and the slope based QRS offset are close
roysandberg 62:8e2fbe131b53 279 // use the isoelectic based point.
roysandberg 62:8e2fbe131b53 280
roysandberg 62:8e2fbe131b53 281 if(isoEnd - *offset < BEAT_MS50)
roysandberg 62:8e2fbe131b53 282 *offset = isoEnd ;
roysandberg 62:8e2fbe131b53 283
roysandberg 62:8e2fbe131b53 284 *isoLevel = beat[isoStart] ;
roysandberg 62:8e2fbe131b53 285
roysandberg 62:8e2fbe131b53 286
roysandberg 62:8e2fbe131b53 287 // Find the maximum and minimum values in the QRS.
roysandberg 62:8e2fbe131b53 288
roysandberg 62:8e2fbe131b53 289 for(i = *onset, maxV = minV = beat[*onset]; i < *offset; ++i)
roysandberg 62:8e2fbe131b53 290 if(beat[i] > maxV)
roysandberg 62:8e2fbe131b53 291 maxV = beat[i] ;
roysandberg 62:8e2fbe131b53 292 else if(beat[i] < minV)
roysandberg 62:8e2fbe131b53 293 minV = beat[i] ;
roysandberg 62:8e2fbe131b53 294
roysandberg 62:8e2fbe131b53 295 // If the offset is significantly below the onset and the offset is
roysandberg 62:8e2fbe131b53 296 // on a negative slope, add the next up slope to the width.
roysandberg 62:8e2fbe131b53 297
roysandberg 62:8e2fbe131b53 298 if((beat[*onset]-beat[*offset] > ((maxV-minV)>>2)+((maxV-minV)>>3)))
roysandberg 62:8e2fbe131b53 299 {
roysandberg 62:8e2fbe131b53 300
roysandberg 62:8e2fbe131b53 301 // Find the maximum slope between the finish and the end of the buffer.
roysandberg 62:8e2fbe131b53 302
roysandberg 62:8e2fbe131b53 303 for(i = maxSlopeI = *offset, maxSlope = beat[*offset] - beat[*offset-1];
roysandberg 62:8e2fbe131b53 304 (i < *offset+BEAT_MS100) && (i < BEATLGTH); ++i)
roysandberg 62:8e2fbe131b53 305 {
roysandberg 62:8e2fbe131b53 306 slope = beat[i]-beat[i-1] ;
roysandberg 62:8e2fbe131b53 307 if(slope > maxSlope)
roysandberg 62:8e2fbe131b53 308 {
roysandberg 62:8e2fbe131b53 309 maxSlope = slope ;
roysandberg 62:8e2fbe131b53 310 maxSlopeI = i ;
roysandberg 62:8e2fbe131b53 311 }
roysandberg 62:8e2fbe131b53 312 }
roysandberg 62:8e2fbe131b53 313
roysandberg 62:8e2fbe131b53 314 // Find the new offset.
roysandberg 62:8e2fbe131b53 315
roysandberg 62:8e2fbe131b53 316 if(maxSlope > 0)
roysandberg 62:8e2fbe131b53 317 {
roysandberg 62:8e2fbe131b53 318 for(i = maxSlopeI;
roysandberg 62:8e2fbe131b53 319 (i < BEATLGTH) && (beat[i]-beat[i-1] > (maxSlope>>1)); ++i) ;
roysandberg 62:8e2fbe131b53 320 *offset = i ;
roysandberg 62:8e2fbe131b53 321 }
roysandberg 62:8e2fbe131b53 322 }
roysandberg 62:8e2fbe131b53 323
roysandberg 62:8e2fbe131b53 324 // Determine beginning and ending of the beat.
roysandberg 62:8e2fbe131b53 325 // Search for an isoelectric region that precedes the R-wave.
roysandberg 62:8e2fbe131b53 326 // by at least 250 ms.
roysandberg 62:8e2fbe131b53 327
roysandberg 62:8e2fbe131b53 328 for(i = FIDMARK-BEAT_MS250;
roysandberg 62:8e2fbe131b53 329 (i >= BEAT_MS80) && (IsoCheck(&beat[i-BEAT_MS80],BEAT_MS80) == 0); --i) ;
roysandberg 62:8e2fbe131b53 330 *beatBegin = i ;
roysandberg 62:8e2fbe131b53 331
roysandberg 62:8e2fbe131b53 332 // If there was an isoelectric section at 250 ms before the
roysandberg 62:8e2fbe131b53 333 // R-wave, search forward for the isoelectric region closest
roysandberg 62:8e2fbe131b53 334 // to the R-wave. But leave at least 50 ms between beat begin
roysandberg 62:8e2fbe131b53 335 // and onset, or else normal beat onset is within PVC QRS complexes.
roysandberg 62:8e2fbe131b53 336 // that screws up noise estimation.
roysandberg 62:8e2fbe131b53 337
roysandberg 62:8e2fbe131b53 338 if(*beatBegin == FIDMARK-BEAT_MS250)
roysandberg 62:8e2fbe131b53 339 {
roysandberg 62:8e2fbe131b53 340 for(; (i < *onset-BEAT_MS50) &&
roysandberg 62:8e2fbe131b53 341 (IsoCheck(&beat[i-BEAT_MS80],BEAT_MS80) == 1); ++i) ;
roysandberg 62:8e2fbe131b53 342 *beatBegin = i-1 ;
roysandberg 62:8e2fbe131b53 343 }
roysandberg 62:8e2fbe131b53 344
roysandberg 62:8e2fbe131b53 345 // Rev 1.1
roysandberg 62:8e2fbe131b53 346 else if(*beatBegin == BEAT_MS80 - 1)
roysandberg 62:8e2fbe131b53 347 {
roysandberg 62:8e2fbe131b53 348 for(; (i < *onset) && (IsoCheck(&beat[i-BEAT_MS80],BEAT_MS80) == 0); ++i);
roysandberg 62:8e2fbe131b53 349 if(i < *onset)
roysandberg 62:8e2fbe131b53 350 {
roysandberg 62:8e2fbe131b53 351 for(; (i < *onset) && (IsoCheck(&beat[i-BEAT_MS80],BEAT_MS80) == 1); ++i) ;
roysandberg 62:8e2fbe131b53 352 if(i < *onset)
roysandberg 62:8e2fbe131b53 353 *beatBegin = i-1 ;
roysandberg 62:8e2fbe131b53 354 }
roysandberg 62:8e2fbe131b53 355 }
roysandberg 62:8e2fbe131b53 356
roysandberg 62:8e2fbe131b53 357 // Search for the end of the beat as the first isoelectric
roysandberg 62:8e2fbe131b53 358 // segment that follows the beat by at least 300 ms.
roysandberg 62:8e2fbe131b53 359
roysandberg 62:8e2fbe131b53 360 for(i = FIDMARK+BEAT_MS300;
roysandberg 62:8e2fbe131b53 361 (i < BEATLGTH) && (IsoCheck(&beat[i],BEAT_MS80) == 0); ++i) ;
roysandberg 62:8e2fbe131b53 362 *beatEnd = i ;
roysandberg 62:8e2fbe131b53 363
roysandberg 62:8e2fbe131b53 364 // If the signal was isoelectric at 300 ms. search backwards.
roysandberg 62:8e2fbe131b53 365 /* if(*beatEnd == FIDMARK+30)
roysandberg 62:8e2fbe131b53 366 {
roysandberg 62:8e2fbe131b53 367 for(; (i > *offset) && (IsoCheck(&beat[i],8) != 0); --i) ;
roysandberg 62:8e2fbe131b53 368 *beatEnd = i ;
roysandberg 62:8e2fbe131b53 369 }
roysandberg 62:8e2fbe131b53 370 */
roysandberg 62:8e2fbe131b53 371 // Calculate beat amplitude.
roysandberg 62:8e2fbe131b53 372
roysandberg 62:8e2fbe131b53 373 maxV=minV=beat[*onset] ;
roysandberg 62:8e2fbe131b53 374 for(i = *onset; i < *offset; ++i)
roysandberg 62:8e2fbe131b53 375 if(beat[i] > maxV)
roysandberg 62:8e2fbe131b53 376 maxV = beat[i] ;
roysandberg 62:8e2fbe131b53 377 else if(beat[i] < minV)
roysandberg 62:8e2fbe131b53 378 minV = beat[i] ;
roysandberg 62:8e2fbe131b53 379 *amp = maxV-minV ;
roysandberg 62:8e2fbe131b53 380
roysandberg 62:8e2fbe131b53 381 }
roysandberg 62:8e2fbe131b53 382
roysandberg 62:8e2fbe131b53 383
roysandberg 62:8e2fbe131b53 384