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: rythmchk.cpp
roysandberg 62:8e2fbe131b53 3 AUTHOR: Patrick S. Hamilton
roysandberg 62:8e2fbe131b53 4 REVISED: 5/13/2002
roysandberg 62:8e2fbe131b53 5 10/9/2001: 1.1 Call premature for 12.5% difference with very regular
roysandberg 62:8e2fbe131b53 6 rhythms. If short after VV go to QQ.
roysandberg 62:8e2fbe131b53 7 5/13/2002: Check for NNVNNNV pattern when last interval was QQ.
roysandberg 62:8e2fbe131b53 8 ___________________________________________________________________________
roysandberg 62:8e2fbe131b53 9
roysandberg 62:8e2fbe131b53 10 rythmchk.cpp: Rhythm Check
roysandberg 62:8e2fbe131b53 11 Copywrite (C) 2001 Patrick S. Hamilton
roysandberg 62:8e2fbe131b53 12
roysandberg 62:8e2fbe131b53 13 This file is free software; you can redistribute it and/or modify it under
roysandberg 62:8e2fbe131b53 14 the terms of the GNU Library General Public License as published by the Free
roysandberg 62:8e2fbe131b53 15 Software Foundation; either version 2 of the License, or (at your option) any
roysandberg 62:8e2fbe131b53 16 later version.
roysandberg 62:8e2fbe131b53 17
roysandberg 62:8e2fbe131b53 18 This software is distributed in the hope that it will be useful, but WITHOUT ANY
roysandberg 62:8e2fbe131b53 19 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
roysandberg 62:8e2fbe131b53 20 PARTICULAR PURPOSE. See the GNU Library General Public License for more
roysandberg 62:8e2fbe131b53 21 details.
roysandberg 62:8e2fbe131b53 22
roysandberg 62:8e2fbe131b53 23 You should have received a copy of the GNU Library General Public License along
roysandberg 62:8e2fbe131b53 24 with this library; if not, write to the Free Software Foundation, Inc., 59
roysandberg 62:8e2fbe131b53 25 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
roysandberg 62:8e2fbe131b53 26
roysandberg 62:8e2fbe131b53 27 You may contact the author by e-mail (pat@eplimited.edu) or postal mail
roysandberg 62:8e2fbe131b53 28 (Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
roysandberg 62:8e2fbe131b53 29 MA 02143 USA). For updates to this software, please visit our website
roysandberg 62:8e2fbe131b53 30 (http://www.eplimited.com).
roysandberg 62:8e2fbe131b53 31 __________________________________________________________________________
roysandberg 62:8e2fbe131b53 32
roysandberg 62:8e2fbe131b53 33 Rythmchk.cpp contains functions for classifying RR intervals as either
roysandberg 62:8e2fbe131b53 34 NORMAL, PVC, or UNKNOWN. Intervals classified as NORMAL are presumed to
roysandberg 62:8e2fbe131b53 35 end with normal beats, intervals classified as PVC are presumed to end
roysandberg 62:8e2fbe131b53 36 with a premature contraction, and intervals classified as unknown do
roysandberg 62:8e2fbe131b53 37 not fit any pattern that the rhythm classifier recognizes.
roysandberg 62:8e2fbe131b53 38
roysandberg 62:8e2fbe131b53 39 NORMAL intervals can be part of a normal (regular) rhythm, normal beats
roysandberg 62:8e2fbe131b53 40 following a premature beats, or normal beats following runs of ventricular
roysandberg 62:8e2fbe131b53 41 beats. PVC intervals can be short intervals following a regular rhythm,
roysandberg 62:8e2fbe131b53 42 short intervals that are part of a run of short intervals following a
roysandberg 62:8e2fbe131b53 43 regular rhythm, or short intervals that are part of a bigeminal rhythm.
roysandberg 62:8e2fbe131b53 44
roysandberg 62:8e2fbe131b53 45 **************************************************************************/
roysandberg 62:8e2fbe131b53 46
roysandberg 62:8e2fbe131b53 47 #include <mbed.h>
roysandberg 62:8e2fbe131b53 48 #include "qrsdet.h" // For time intervals.
roysandberg 62:8e2fbe131b53 49 #include "ecgcodes.h" // Defines codes of NORMAL, PVC, and UNKNOWN.
roysandberg 62:8e2fbe131b53 50 //#include <stdlib.h> // For abs()
roysandberg 62:8e2fbe131b53 51
roysandberg 62:8e2fbe131b53 52 // Define RR interval types.
roysandberg 62:8e2fbe131b53 53
roysandberg 62:8e2fbe131b53 54 #define QQ 0 // Unknown-Unknown interval.
roysandberg 62:8e2fbe131b53 55 #define NN 1 // Normal-Normal interval.
roysandberg 62:8e2fbe131b53 56 #define NV 2 // Normal-PVC interval.
roysandberg 62:8e2fbe131b53 57 #define VN 3 // PVC-Normal interval.
roysandberg 62:8e2fbe131b53 58 #define VV 4 // PVC-PVC interval.
roysandberg 62:8e2fbe131b53 59
roysandberg 62:8e2fbe131b53 60 #define RBB_LENGTH 8
roysandberg 62:8e2fbe131b53 61 #define LEARNING 0
roysandberg 62:8e2fbe131b53 62 #define READY 1
roysandberg 62:8e2fbe131b53 63
roysandberg 62:8e2fbe131b53 64 #define BRADY_LIMIT MS1500
roysandberg 62:8e2fbe131b53 65
roysandberg 62:8e2fbe131b53 66 // Local prototypes.
roysandberg 62:8e2fbe131b53 67 int RRMatch(int rr0,int rr1) ;
roysandberg 62:8e2fbe131b53 68 int RRShort(int rr0,int rr1) ;
roysandberg 62:8e2fbe131b53 69 int RRShort2(int *rrIntervals, int *rrTypes) ;
roysandberg 62:8e2fbe131b53 70 int RRMatch2(int rr0,int rr1) ;
roysandberg 62:8e2fbe131b53 71
roysandberg 62:8e2fbe131b53 72 // Global variables.
roysandberg 62:8e2fbe131b53 73 int RRBuffer[RBB_LENGTH], RRTypes[RBB_LENGTH], BeatCount = 0;
roysandberg 62:8e2fbe131b53 74 int ClassifyState = LEARNING ;
roysandberg 62:8e2fbe131b53 75
roysandberg 62:8e2fbe131b53 76 int BigeminyFlag ;
roysandberg 62:8e2fbe131b53 77
roysandberg 62:8e2fbe131b53 78 /***************************************************************************
roysandberg 62:8e2fbe131b53 79 ResetRhythmChk() resets static variables used for rhythm classification.
roysandberg 62:8e2fbe131b53 80 ****************************************************************************/
roysandberg 62:8e2fbe131b53 81
roysandberg 62:8e2fbe131b53 82 void ResetRhythmChk(void)
roysandberg 62:8e2fbe131b53 83 {
roysandberg 62:8e2fbe131b53 84 BeatCount = 0 ;
roysandberg 62:8e2fbe131b53 85 ClassifyState = LEARNING ;
roysandberg 62:8e2fbe131b53 86 }
roysandberg 62:8e2fbe131b53 87
roysandberg 62:8e2fbe131b53 88 /*****************************************************************************
roysandberg 62:8e2fbe131b53 89 RhythmChk() takes an R-to-R interval as input and, based on previous R-to-R
roysandberg 62:8e2fbe131b53 90 intervals, classifys the interval as NORMAL, PVC, or UNKNOWN.
roysandberg 62:8e2fbe131b53 91 ******************************************************************************/
roysandberg 62:8e2fbe131b53 92
roysandberg 62:8e2fbe131b53 93 int RhythmChk(int rr)
roysandberg 62:8e2fbe131b53 94 {
roysandberg 62:8e2fbe131b53 95 int i, regular = 1 ;
roysandberg 62:8e2fbe131b53 96 int NNEst, NVEst ;
roysandberg 62:8e2fbe131b53 97
roysandberg 62:8e2fbe131b53 98 BigeminyFlag = 0 ;
roysandberg 62:8e2fbe131b53 99
roysandberg 62:8e2fbe131b53 100 // Wait for at least 4 beats before classifying anything.
roysandberg 62:8e2fbe131b53 101
roysandberg 62:8e2fbe131b53 102 if(BeatCount < 4)
roysandberg 62:8e2fbe131b53 103 {
roysandberg 62:8e2fbe131b53 104 if(++BeatCount == 4)
roysandberg 62:8e2fbe131b53 105 ClassifyState = READY ;
roysandberg 62:8e2fbe131b53 106 }
roysandberg 62:8e2fbe131b53 107
roysandberg 62:8e2fbe131b53 108 // Stick the new RR interval into the RR interval Buffer.
roysandberg 62:8e2fbe131b53 109
roysandberg 62:8e2fbe131b53 110 for(i = RBB_LENGTH-1; i > 0; --i)
roysandberg 62:8e2fbe131b53 111 {
roysandberg 62:8e2fbe131b53 112 RRBuffer[i] = RRBuffer[i-1] ;
roysandberg 62:8e2fbe131b53 113 RRTypes[i] = RRTypes[i-1] ;
roysandberg 62:8e2fbe131b53 114 }
roysandberg 62:8e2fbe131b53 115
roysandberg 62:8e2fbe131b53 116 RRBuffer[0] = rr ;
roysandberg 62:8e2fbe131b53 117
roysandberg 62:8e2fbe131b53 118 if(ClassifyState == LEARNING)
roysandberg 62:8e2fbe131b53 119 {
roysandberg 62:8e2fbe131b53 120 RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 121 return(UNKNOWN) ;
roysandberg 62:8e2fbe131b53 122 }
roysandberg 62:8e2fbe131b53 123
roysandberg 62:8e2fbe131b53 124 // If we couldn't tell what the last interval was...
roysandberg 62:8e2fbe131b53 125
roysandberg 62:8e2fbe131b53 126 if(RRTypes[1] == QQ)
roysandberg 62:8e2fbe131b53 127 {
roysandberg 62:8e2fbe131b53 128 for(i = 0, regular = 1; i < 3; ++i)
roysandberg 62:8e2fbe131b53 129 if(RRMatch(RRBuffer[i],RRBuffer[i+1]) == 0)
roysandberg 62:8e2fbe131b53 130 regular = 0 ;
roysandberg 62:8e2fbe131b53 131
roysandberg 62:8e2fbe131b53 132 // If this, and the last three intervals matched, classify
roysandberg 62:8e2fbe131b53 133 // it as Normal-Normal.
roysandberg 62:8e2fbe131b53 134
roysandberg 62:8e2fbe131b53 135 if(regular == 1)
roysandberg 62:8e2fbe131b53 136 {
roysandberg 62:8e2fbe131b53 137 RRTypes[0] = NN ;
roysandberg 62:8e2fbe131b53 138 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 139 }
roysandberg 62:8e2fbe131b53 140
roysandberg 62:8e2fbe131b53 141 // Check for bigeminy.
roysandberg 62:8e2fbe131b53 142 // Call bigeminy if every other RR matches and
roysandberg 62:8e2fbe131b53 143 // consecutive beats do not match.
roysandberg 62:8e2fbe131b53 144
roysandberg 62:8e2fbe131b53 145 for(i = 0, regular = 1; i < 6; ++i)
roysandberg 62:8e2fbe131b53 146 if(RRMatch(RRBuffer[i],RRBuffer[i+2]) == 0)
roysandberg 62:8e2fbe131b53 147 regular = 0 ;
roysandberg 62:8e2fbe131b53 148 for(i = 0; i < 6; ++i)
roysandberg 62:8e2fbe131b53 149 if(RRMatch(RRBuffer[i],RRBuffer[i+1]) != 0)
roysandberg 62:8e2fbe131b53 150 regular = 0 ;
roysandberg 62:8e2fbe131b53 151
roysandberg 62:8e2fbe131b53 152 if(regular == 1)
roysandberg 62:8e2fbe131b53 153 {
roysandberg 62:8e2fbe131b53 154 BigeminyFlag = 1 ;
roysandberg 62:8e2fbe131b53 155 if(RRBuffer[0] < RRBuffer[1])
roysandberg 62:8e2fbe131b53 156 {
roysandberg 62:8e2fbe131b53 157 RRTypes[0] = NV ;
roysandberg 62:8e2fbe131b53 158 RRTypes[1] = VN ;
roysandberg 62:8e2fbe131b53 159 return(PVC) ;
roysandberg 62:8e2fbe131b53 160 }
roysandberg 62:8e2fbe131b53 161 else
roysandberg 62:8e2fbe131b53 162 {
roysandberg 62:8e2fbe131b53 163 RRTypes[0] = VN ;
roysandberg 62:8e2fbe131b53 164 RRTypes[1] = NV ;
roysandberg 62:8e2fbe131b53 165 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 166 }
roysandberg 62:8e2fbe131b53 167 }
roysandberg 62:8e2fbe131b53 168
roysandberg 62:8e2fbe131b53 169 // Check for NNVNNNV pattern.
roysandberg 62:8e2fbe131b53 170
roysandberg 62:8e2fbe131b53 171 if(RRShort(RRBuffer[0],RRBuffer[1]) && RRMatch(RRBuffer[1],RRBuffer[2])
roysandberg 62:8e2fbe131b53 172 && RRMatch(RRBuffer[2]*2,RRBuffer[3]+RRBuffer[4]) &&
roysandberg 62:8e2fbe131b53 173 RRMatch(RRBuffer[4],RRBuffer[0]) && RRMatch(RRBuffer[5],RRBuffer[2]))
roysandberg 62:8e2fbe131b53 174 {
roysandberg 62:8e2fbe131b53 175 RRTypes[0] = NV ;
roysandberg 62:8e2fbe131b53 176 RRTypes[1] = NN ;
roysandberg 62:8e2fbe131b53 177 return(PVC) ;
roysandberg 62:8e2fbe131b53 178 }
roysandberg 62:8e2fbe131b53 179
roysandberg 62:8e2fbe131b53 180 // If the interval is not part of a
roysandberg 62:8e2fbe131b53 181 // bigeminal or regular pattern, give up.
roysandberg 62:8e2fbe131b53 182
roysandberg 62:8e2fbe131b53 183 else
roysandberg 62:8e2fbe131b53 184 {
roysandberg 62:8e2fbe131b53 185 RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 186 return(UNKNOWN) ;
roysandberg 62:8e2fbe131b53 187 }
roysandberg 62:8e2fbe131b53 188 }
roysandberg 62:8e2fbe131b53 189
roysandberg 62:8e2fbe131b53 190 // If the previous two beats were normal...
roysandberg 62:8e2fbe131b53 191
roysandberg 62:8e2fbe131b53 192 else if(RRTypes[1] == NN)
roysandberg 62:8e2fbe131b53 193 {
roysandberg 62:8e2fbe131b53 194
roysandberg 62:8e2fbe131b53 195 if(RRShort2(RRBuffer,RRTypes))
roysandberg 62:8e2fbe131b53 196 {
roysandberg 62:8e2fbe131b53 197 if(RRBuffer[1] < BRADY_LIMIT)
roysandberg 62:8e2fbe131b53 198 {
roysandberg 62:8e2fbe131b53 199 RRTypes[0] = NV ;
roysandberg 62:8e2fbe131b53 200 return(PVC) ;
roysandberg 62:8e2fbe131b53 201 }
roysandberg 62:8e2fbe131b53 202 else RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 203 return(UNKNOWN) ;
roysandberg 62:8e2fbe131b53 204 }
roysandberg 62:8e2fbe131b53 205
roysandberg 62:8e2fbe131b53 206
roysandberg 62:8e2fbe131b53 207 // If this interval matches the previous interval, then it
roysandberg 62:8e2fbe131b53 208 // is regular.
roysandberg 62:8e2fbe131b53 209
roysandberg 62:8e2fbe131b53 210 else if(RRMatch(RRBuffer[0],RRBuffer[1]))
roysandberg 62:8e2fbe131b53 211 {
roysandberg 62:8e2fbe131b53 212 RRTypes[0] = NN ;
roysandberg 62:8e2fbe131b53 213 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 214 }
roysandberg 62:8e2fbe131b53 215
roysandberg 62:8e2fbe131b53 216 // If this interval is short..
roysandberg 62:8e2fbe131b53 217
roysandberg 62:8e2fbe131b53 218 else if(RRShort(RRBuffer[0],RRBuffer[1]))
roysandberg 62:8e2fbe131b53 219 {
roysandberg 62:8e2fbe131b53 220
roysandberg 62:8e2fbe131b53 221 // But matches the one before last and the one before
roysandberg 62:8e2fbe131b53 222 // last was NN, this is a normal interval.
roysandberg 62:8e2fbe131b53 223
roysandberg 62:8e2fbe131b53 224 if(RRMatch(RRBuffer[0],RRBuffer[2]) && (RRTypes[2] == NN))
roysandberg 62:8e2fbe131b53 225 {
roysandberg 62:8e2fbe131b53 226 RRTypes[0] = NN ;
roysandberg 62:8e2fbe131b53 227 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 228 }
roysandberg 62:8e2fbe131b53 229
roysandberg 62:8e2fbe131b53 230 // If the rhythm wasn't bradycardia, call it a PVC.
roysandberg 62:8e2fbe131b53 231
roysandberg 62:8e2fbe131b53 232 else if(RRBuffer[1] < BRADY_LIMIT)
roysandberg 62:8e2fbe131b53 233 {
roysandberg 62:8e2fbe131b53 234 RRTypes[0] = NV ;
roysandberg 62:8e2fbe131b53 235 return(PVC) ;
roysandberg 62:8e2fbe131b53 236 }
roysandberg 62:8e2fbe131b53 237
roysandberg 62:8e2fbe131b53 238 // If the regular rhythm was bradycardia, don't assume that
roysandberg 62:8e2fbe131b53 239 // it was a PVC.
roysandberg 62:8e2fbe131b53 240
roysandberg 62:8e2fbe131b53 241 else
roysandberg 62:8e2fbe131b53 242 {
roysandberg 62:8e2fbe131b53 243 RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 244 return(UNKNOWN) ;
roysandberg 62:8e2fbe131b53 245 }
roysandberg 62:8e2fbe131b53 246 }
roysandberg 62:8e2fbe131b53 247
roysandberg 62:8e2fbe131b53 248 // If the interval isn't normal or short, then classify
roysandberg 62:8e2fbe131b53 249 // it as normal but don't assume normal for future
roysandberg 62:8e2fbe131b53 250 // rhythm classification.
roysandberg 62:8e2fbe131b53 251
roysandberg 62:8e2fbe131b53 252 else
roysandberg 62:8e2fbe131b53 253 {
roysandberg 62:8e2fbe131b53 254 RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 255 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 256 }
roysandberg 62:8e2fbe131b53 257 }
roysandberg 62:8e2fbe131b53 258
roysandberg 62:8e2fbe131b53 259 // If the previous beat was a PVC...
roysandberg 62:8e2fbe131b53 260
roysandberg 62:8e2fbe131b53 261 else if(RRTypes[1] == NV)
roysandberg 62:8e2fbe131b53 262 {
roysandberg 62:8e2fbe131b53 263
roysandberg 62:8e2fbe131b53 264 if(RRShort2(&RRBuffer[1],&RRTypes[1]))
roysandberg 62:8e2fbe131b53 265 {
roysandberg 62:8e2fbe131b53 266 /* if(RRMatch2(RRBuffer[0],RRBuffer[1]))
roysandberg 62:8e2fbe131b53 267 {
roysandberg 62:8e2fbe131b53 268 RRTypes[0] = VV ;
roysandberg 62:8e2fbe131b53 269 return(PVC) ;
roysandberg 62:8e2fbe131b53 270 } */
roysandberg 62:8e2fbe131b53 271
roysandberg 62:8e2fbe131b53 272 if(RRMatch(RRBuffer[0],RRBuffer[1]))
roysandberg 62:8e2fbe131b53 273 {
roysandberg 62:8e2fbe131b53 274 RRTypes[0] = NN ;
roysandberg 62:8e2fbe131b53 275 RRTypes[1] = NN ;
roysandberg 62:8e2fbe131b53 276 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 277 }
roysandberg 62:8e2fbe131b53 278 else if(RRBuffer[0] > RRBuffer[1])
roysandberg 62:8e2fbe131b53 279 {
roysandberg 62:8e2fbe131b53 280 RRTypes[0] = VN ;
roysandberg 62:8e2fbe131b53 281 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 282 }
roysandberg 62:8e2fbe131b53 283 else
roysandberg 62:8e2fbe131b53 284 {
roysandberg 62:8e2fbe131b53 285 RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 286 return(UNKNOWN) ;
roysandberg 62:8e2fbe131b53 287 }
roysandberg 62:8e2fbe131b53 288
roysandberg 62:8e2fbe131b53 289
roysandberg 62:8e2fbe131b53 290 }
roysandberg 62:8e2fbe131b53 291
roysandberg 62:8e2fbe131b53 292 // If this interval matches the previous premature
roysandberg 62:8e2fbe131b53 293 // interval assume a ventricular couplet.
roysandberg 62:8e2fbe131b53 294
roysandberg 62:8e2fbe131b53 295 else if(RRMatch(RRBuffer[0],RRBuffer[1]))
roysandberg 62:8e2fbe131b53 296 {
roysandberg 62:8e2fbe131b53 297 RRTypes[0] = VV ;
roysandberg 62:8e2fbe131b53 298 return(PVC) ;
roysandberg 62:8e2fbe131b53 299 }
roysandberg 62:8e2fbe131b53 300
roysandberg 62:8e2fbe131b53 301 // If this interval is larger than the previous
roysandberg 62:8e2fbe131b53 302 // interval, assume that it is NORMAL.
roysandberg 62:8e2fbe131b53 303
roysandberg 62:8e2fbe131b53 304 else if(RRBuffer[0] > RRBuffer[1])
roysandberg 62:8e2fbe131b53 305 {
roysandberg 62:8e2fbe131b53 306 RRTypes[0] = VN ;
roysandberg 62:8e2fbe131b53 307 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 308 }
roysandberg 62:8e2fbe131b53 309
roysandberg 62:8e2fbe131b53 310 // Otherwise don't make any assumputions about
roysandberg 62:8e2fbe131b53 311 // what this interval represents.
roysandberg 62:8e2fbe131b53 312
roysandberg 62:8e2fbe131b53 313 else
roysandberg 62:8e2fbe131b53 314 {
roysandberg 62:8e2fbe131b53 315 RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 316 return(UNKNOWN) ;
roysandberg 62:8e2fbe131b53 317 }
roysandberg 62:8e2fbe131b53 318 }
roysandberg 62:8e2fbe131b53 319
roysandberg 62:8e2fbe131b53 320 // If the previous beat followed a PVC or couplet etc...
roysandberg 62:8e2fbe131b53 321
roysandberg 62:8e2fbe131b53 322 else if(RRTypes[1] == VN)
roysandberg 62:8e2fbe131b53 323 {
roysandberg 62:8e2fbe131b53 324
roysandberg 62:8e2fbe131b53 325 // Find the last NN interval.
roysandberg 62:8e2fbe131b53 326
roysandberg 62:8e2fbe131b53 327 for(i = 2; (RRTypes[i] != NN) && (i < RBB_LENGTH); ++i) ;
roysandberg 62:8e2fbe131b53 328
roysandberg 62:8e2fbe131b53 329 // If there was an NN interval in the interval buffer...
roysandberg 62:8e2fbe131b53 330 if(i != RBB_LENGTH)
roysandberg 62:8e2fbe131b53 331 {
roysandberg 62:8e2fbe131b53 332 NNEst = RRBuffer[i] ;
roysandberg 62:8e2fbe131b53 333
roysandberg 62:8e2fbe131b53 334 // and it matches, classify this interval as NORMAL.
roysandberg 62:8e2fbe131b53 335
roysandberg 62:8e2fbe131b53 336 if(RRMatch(RRBuffer[0],NNEst))
roysandberg 62:8e2fbe131b53 337 {
roysandberg 62:8e2fbe131b53 338 RRTypes[0] = NN ;
roysandberg 62:8e2fbe131b53 339 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 340 }
roysandberg 62:8e2fbe131b53 341 }
roysandberg 62:8e2fbe131b53 342
roysandberg 62:8e2fbe131b53 343 else NNEst = 0 ;
roysandberg 62:8e2fbe131b53 344 for(i = 2; (RRTypes[i] != NV) && (i < RBB_LENGTH); ++i) ;
roysandberg 62:8e2fbe131b53 345 if(i != RBB_LENGTH)
roysandberg 62:8e2fbe131b53 346 NVEst = RRBuffer[i] ;
roysandberg 62:8e2fbe131b53 347 else NVEst = 0 ;
roysandberg 62:8e2fbe131b53 348 if((NNEst == 0) && (NVEst != 0))
roysandberg 62:8e2fbe131b53 349 NNEst = (RRBuffer[1]+NVEst) >> 1 ;
roysandberg 62:8e2fbe131b53 350
roysandberg 62:8e2fbe131b53 351 // NNEst is either the last NN interval or the average
roysandberg 62:8e2fbe131b53 352 // of the most recent NV and VN intervals.
roysandberg 62:8e2fbe131b53 353
roysandberg 62:8e2fbe131b53 354 // If the interval is closer to NN than NV, try
roysandberg 62:8e2fbe131b53 355 // matching to NN.
roysandberg 62:8e2fbe131b53 356
roysandberg 62:8e2fbe131b53 357 if((NVEst != 0) &&
roysandberg 62:8e2fbe131b53 358 (abs(NNEst - RRBuffer[0]) < abs(NVEst - RRBuffer[0])) &&
roysandberg 62:8e2fbe131b53 359 RRMatch(NNEst,RRBuffer[0]))
roysandberg 62:8e2fbe131b53 360 {
roysandberg 62:8e2fbe131b53 361 RRTypes[0] = NN ;
roysandberg 62:8e2fbe131b53 362 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 363 }
roysandberg 62:8e2fbe131b53 364
roysandberg 62:8e2fbe131b53 365 // If this interval is closer to NV than NN, try
roysandberg 62:8e2fbe131b53 366 // matching to NV.
roysandberg 62:8e2fbe131b53 367
roysandberg 62:8e2fbe131b53 368 else if((NVEst != 0) &&
roysandberg 62:8e2fbe131b53 369 (abs(NNEst - RRBuffer[0]) > abs(NVEst - RRBuffer[0])) &&
roysandberg 62:8e2fbe131b53 370 RRMatch(NVEst,RRBuffer[0]))
roysandberg 62:8e2fbe131b53 371 {
roysandberg 62:8e2fbe131b53 372 RRTypes[0] = NV ;
roysandberg 62:8e2fbe131b53 373 return(PVC) ;
roysandberg 62:8e2fbe131b53 374 }
roysandberg 62:8e2fbe131b53 375
roysandberg 62:8e2fbe131b53 376 // If equally close, or we don't have an NN or NV in the buffer,
roysandberg 62:8e2fbe131b53 377 // who knows what it is.
roysandberg 62:8e2fbe131b53 378
roysandberg 62:8e2fbe131b53 379 else
roysandberg 62:8e2fbe131b53 380 {
roysandberg 62:8e2fbe131b53 381 RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 382 return(UNKNOWN) ;
roysandberg 62:8e2fbe131b53 383 }
roysandberg 62:8e2fbe131b53 384 }
roysandberg 62:8e2fbe131b53 385
roysandberg 62:8e2fbe131b53 386 // Otherwise the previous interval must have been a VV
roysandberg 62:8e2fbe131b53 387
roysandberg 62:8e2fbe131b53 388 else
roysandberg 62:8e2fbe131b53 389 {
roysandberg 62:8e2fbe131b53 390
roysandberg 62:8e2fbe131b53 391 // Does this match previous VV.
roysandberg 62:8e2fbe131b53 392
roysandberg 62:8e2fbe131b53 393 if(RRMatch(RRBuffer[0],RRBuffer[1]))
roysandberg 62:8e2fbe131b53 394 {
roysandberg 62:8e2fbe131b53 395 RRTypes[0] = VV ;
roysandberg 62:8e2fbe131b53 396 return(PVC) ;
roysandberg 62:8e2fbe131b53 397 }
roysandberg 62:8e2fbe131b53 398
roysandberg 62:8e2fbe131b53 399 // If this doesn't match a previous VV interval, assume
roysandberg 62:8e2fbe131b53 400 // any new interval is recovery to Normal beat.
roysandberg 62:8e2fbe131b53 401
roysandberg 62:8e2fbe131b53 402 else
roysandberg 62:8e2fbe131b53 403 {
roysandberg 62:8e2fbe131b53 404 if(RRShort(RRBuffer[0],RRBuffer[1]))
roysandberg 62:8e2fbe131b53 405 {
roysandberg 62:8e2fbe131b53 406 RRTypes[0] = QQ ;
roysandberg 62:8e2fbe131b53 407 return(UNKNOWN) ;
roysandberg 62:8e2fbe131b53 408 }
roysandberg 62:8e2fbe131b53 409 else
roysandberg 62:8e2fbe131b53 410 {
roysandberg 62:8e2fbe131b53 411 RRTypes[0] = VN ;
roysandberg 62:8e2fbe131b53 412 return(NORMAL) ;
roysandberg 62:8e2fbe131b53 413 }
roysandberg 62:8e2fbe131b53 414 }
roysandberg 62:8e2fbe131b53 415 }
roysandberg 62:8e2fbe131b53 416 }
roysandberg 62:8e2fbe131b53 417
roysandberg 62:8e2fbe131b53 418
roysandberg 62:8e2fbe131b53 419 /***********************************************************************
roysandberg 62:8e2fbe131b53 420 RRMatch() test whether two intervals are within 12.5% of their mean.
roysandberg 62:8e2fbe131b53 421 ************************************************************************/
roysandberg 62:8e2fbe131b53 422
roysandberg 62:8e2fbe131b53 423 int RRMatch(int rr0,int rr1)
roysandberg 62:8e2fbe131b53 424 {
roysandberg 62:8e2fbe131b53 425 if(abs(rr0-rr1) < ((rr0+rr1)>>3))
roysandberg 62:8e2fbe131b53 426 return(1) ;
roysandberg 62:8e2fbe131b53 427 else return(0) ;
roysandberg 62:8e2fbe131b53 428 }
roysandberg 62:8e2fbe131b53 429
roysandberg 62:8e2fbe131b53 430 /************************************************************************
roysandberg 62:8e2fbe131b53 431 RRShort() tests whether an interval is less than 75% of the previous
roysandberg 62:8e2fbe131b53 432 interval.
roysandberg 62:8e2fbe131b53 433 *************************************************************************/
roysandberg 62:8e2fbe131b53 434
roysandberg 62:8e2fbe131b53 435 int RRShort(int rr0, int rr1)
roysandberg 62:8e2fbe131b53 436 {
roysandberg 62:8e2fbe131b53 437 if(rr0 < rr1-(rr1>>2))
roysandberg 62:8e2fbe131b53 438 return(1) ;
roysandberg 62:8e2fbe131b53 439 else return(0) ;
roysandberg 62:8e2fbe131b53 440 }
roysandberg 62:8e2fbe131b53 441
roysandberg 62:8e2fbe131b53 442 /*************************************************************************
roysandberg 62:8e2fbe131b53 443 IsBigeminy() allows external access to the bigeminy flag to check whether
roysandberg 62:8e2fbe131b53 444 a bigeminal rhythm is in progress.
roysandberg 62:8e2fbe131b53 445 **************************************************************************/
roysandberg 62:8e2fbe131b53 446
roysandberg 62:8e2fbe131b53 447 int IsBigeminy(void)
roysandberg 62:8e2fbe131b53 448 {
roysandberg 62:8e2fbe131b53 449 return(BigeminyFlag) ;
roysandberg 62:8e2fbe131b53 450 }
roysandberg 62:8e2fbe131b53 451
roysandberg 62:8e2fbe131b53 452 /**************************************************************************
roysandberg 62:8e2fbe131b53 453 Check for short interval in very regular rhythm.
roysandberg 62:8e2fbe131b53 454 **************************************************************************/
roysandberg 62:8e2fbe131b53 455
roysandberg 62:8e2fbe131b53 456 int RRShort2(int *rrIntervals, int *rrTypes)
roysandberg 62:8e2fbe131b53 457 {
roysandberg 62:8e2fbe131b53 458 int rrMean = 0, i, nnCount ;
roysandberg 62:8e2fbe131b53 459
roysandberg 62:8e2fbe131b53 460 for(i = 1, nnCount = 0; (i < 7) && (nnCount < 4); ++i)
roysandberg 62:8e2fbe131b53 461 if(rrTypes[i] == NN)
roysandberg 62:8e2fbe131b53 462 {
roysandberg 62:8e2fbe131b53 463 ++nnCount ;
roysandberg 62:8e2fbe131b53 464 rrMean += rrIntervals[i] ;
roysandberg 62:8e2fbe131b53 465 }
roysandberg 62:8e2fbe131b53 466
roysandberg 62:8e2fbe131b53 467 // Return if there aren't at least 4 normal intervals.
roysandberg 62:8e2fbe131b53 468
roysandberg 62:8e2fbe131b53 469 if(nnCount != 4)
roysandberg 62:8e2fbe131b53 470 return(0) ;
roysandberg 62:8e2fbe131b53 471 rrMean >>= 2 ;
roysandberg 62:8e2fbe131b53 472
roysandberg 62:8e2fbe131b53 473
roysandberg 62:8e2fbe131b53 474 for(i = 1, nnCount = 0; (i < 7) && (nnCount < 4); ++i)
roysandberg 62:8e2fbe131b53 475 if(rrTypes[i] == NN)
roysandberg 62:8e2fbe131b53 476 {
roysandberg 62:8e2fbe131b53 477 if(abs(rrMean-rrIntervals[i]) > (rrMean>>4))
roysandberg 62:8e2fbe131b53 478 i = 10 ;
roysandberg 62:8e2fbe131b53 479 }
roysandberg 62:8e2fbe131b53 480
roysandberg 62:8e2fbe131b53 481 if((i < 9) && (rrIntervals[0] < (rrMean - (rrMean>>3))))
roysandberg 62:8e2fbe131b53 482 return(1) ;
roysandberg 62:8e2fbe131b53 483 else
roysandberg 62:8e2fbe131b53 484 return(0) ;
roysandberg 62:8e2fbe131b53 485 }
roysandberg 62:8e2fbe131b53 486
roysandberg 62:8e2fbe131b53 487 int RRMatch2(int rr0,int rr1)
roysandberg 62:8e2fbe131b53 488 {
roysandberg 62:8e2fbe131b53 489 if(abs(rr0-rr1) < ((rr0+rr1)>>4))
roysandberg 62:8e2fbe131b53 490 return(1) ;
roysandberg 62:8e2fbe131b53 491 else return(0) ;
roysandberg 62:8e2fbe131b53 492 }