I've got some basic filter code setup (but not yet tested).
Dependencies: BLE_API Queue mbed nRF51822
Fork of BLE_HeartRate by
rythmchk.cpp@62:8e2fbe131b53, 2015-06-28 (annotated)
- 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?
User | Revision | Line number | New 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 | } |