I've got some basic filter code setup (but not yet tested).
Dependencies: BLE_API Queue mbed nRF51822
Fork of BLE_HeartRate by
Diff: qrsfilt.cpp
- Revision:
- 62:8e2fbe131b53
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qrsfilt.cpp Sun Jun 28 03:06:00 2015 +0000 @@ -0,0 +1,242 @@ +/***************************************************************************** +FILE: qrsfilt.cpp +AUTHOR: Patrick S. Hamilton +REVISED: 5/13/2002 + ___________________________________________________________________________ + +qrsfilt.cpp filter functions to aid beat detecton in electrocardiograms. +Copywrite (C) 2000 Patrick S. Hamilton + +This file is free software; you can redistribute it and/or modify it under +the terms of the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) any +later version. + +This software is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU Library General Public License for more +details. + +You should have received a copy of the GNU Library General Public License along +with this library; if not, write to the Free Software Foundation, Inc., 59 +Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +You may contact the author by e-mail (pat@eplimited.edu) or postal mail +(Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville, +MA 02143 USA). For updates to this software, please visit our website +(http://www.eplimited.com). + __________________________________________________________________________ + + This file includes QRSFilt() and associated filtering files used for QRS + detection. Only QRSFilt() and deriv1() are called by the QRS detector + other functions can be hidden. + + Revisions: + 5/13: Filter implementations have been modified to allow simplified + modification for different sample rates. + +*******************************************************************************/ + +#include <mbed.h> +//#include <math.h> +#include "qrsdet.h" + +// Local Prototypes. + +int lpfilt( int datum ,int init) ; +int hpfilt( int datum, int init ) ; +int deriv1( int x0, int init ) ; +int deriv2( int x0, int init ) ; +int mvwint(int datum, int init) ; + +/****************************************************************************** +* Syntax: +* int QRSFilter(int datum, int init) ; +* Description: +* QRSFilter() takes samples of an ECG signal as input and returns a sample of +* a signal that is an estimate of the local energy in the QRS bandwidth. In +* other words, the signal has a lump in it whenever a QRS complex, or QRS +* complex like artifact occurs. The filters were originally designed for data +* sampled at 200 samples per second, but they work nearly as well at sample +* frequencies from 150 to 250 samples per second. +* +* The filter buffers and static variables are reset if a value other than +* 0 is passed to QRSFilter through init. +*******************************************************************************/ + +int QRSFilter(int datum,int init) + { + int fdatum ; + + if(init) + { + hpfilt( 0, 1 ) ; // Initialize filters. + lpfilt( 0, 1 ) ; + mvwint( 0, 1 ) ; + deriv1( 0, 1 ) ; + deriv2( 0, 1 ) ; + } + + fdatum = lpfilt( datum, 0 ) ; // Low pass filter data. + fdatum = hpfilt( fdatum, 0 ) ; // High pass filter data. + fdatum = deriv2( fdatum, 0 ) ; // Take the derivative. + fdatum = abs(fdatum) ; // Take the absolute value. + fdatum = mvwint( fdatum, 0 ) ; // Average over an 80 ms window . + return(fdatum) ; + } + + +/************************************************************************* +* lpfilt() implements the digital filter represented by the difference +* equation: +* +* y[n] = 2*y[n-1] - y[n-2] + x[n] - 2*x[t-24 ms] + x[t-48 ms] +* +* Note that the filter delay is (LPBUFFER_LGTH/2)-1 +* +**************************************************************************/ + +int lpfilt( int datum ,int init) + { + static long y1 = 0, y2 = 0 ; + static int data[LPBUFFER_LGTH], ptr = 0 ; + long y0 ; + int output, halfPtr ; + if(init) + { + for(ptr = 0; ptr < LPBUFFER_LGTH; ++ptr) + data[ptr] = 0 ; + y1 = y2 = 0 ; + ptr = 0 ; + } + halfPtr = ptr-(LPBUFFER_LGTH/2) ; // Use halfPtr to index + if(halfPtr < 0) // to x[n-6]. + halfPtr += LPBUFFER_LGTH ; + y0 = (y1 << 1) - y2 + datum - (data[halfPtr] << 1) + data[ptr] ; + y2 = y1; + y1 = y0; + output = y0 / ((LPBUFFER_LGTH*LPBUFFER_LGTH)/4); + data[ptr] = datum ; // Stick most recent sample into + if(++ptr == LPBUFFER_LGTH) // the circular buffer and update + ptr = 0 ; // the buffer pointer. + return(output) ; + } + + +/****************************************************************************** +* hpfilt() implements the high pass filter represented by the following +* difference equation: +* +* y[n] = y[n-1] + x[n] - x[n-128 ms] +* z[n] = x[n-64 ms] - y[n] ; +* +* Filter delay is (HPBUFFER_LGTH-1)/2 +******************************************************************************/ + +int hpfilt( int datum, int init ) + { + static long y=0 ; + static int data[HPBUFFER_LGTH], ptr = 0 ; + int z, halfPtr ; + + if(init) + { + for(ptr = 0; ptr < HPBUFFER_LGTH; ++ptr) + data[ptr] = 0 ; + ptr = 0 ; + y = 0 ; + } + + y += datum - data[ptr]; + halfPtr = ptr-(HPBUFFER_LGTH/2) ; + if(halfPtr < 0) + halfPtr += HPBUFFER_LGTH ; + z = data[halfPtr] - (y / HPBUFFER_LGTH); + + data[ptr] = datum ; + if(++ptr == HPBUFFER_LGTH) + ptr = 0 ; + + return( z ); + } + +/***************************************************************************** +* deriv1 and deriv2 implement derivative approximations represented by +* the difference equation: +* +* y[n] = x[n] - x[n - 10ms] +* +* Filter delay is DERIV_LENGTH/2 +*****************************************************************************/ + +int deriv1(int x, int init) + { + static int derBuff[DERIV_LENGTH], derI = 0 ; + int y ; + + if(init != 0) + { + for(derI = 0; derI < DERIV_LENGTH; ++derI) + derBuff[derI] = 0 ; + derI = 0 ; + return(0) ; + } + + y = x - derBuff[derI] ; + derBuff[derI] = x ; + if(++derI == DERIV_LENGTH) + derI = 0 ; + return(y) ; + } + +int deriv2(int x, int init) + { + static int derBuff[DERIV_LENGTH], derI = 0 ; + int y ; + + if(init != 0) + { + for(derI = 0; derI < DERIV_LENGTH; ++derI) + derBuff[derI] = 0 ; + derI = 0 ; + return(0) ; + } + + y = x - derBuff[derI] ; + derBuff[derI] = x ; + if(++derI == DERIV_LENGTH) + derI = 0 ; + return(y) ; + } + + + + +/***************************************************************************** +* mvwint() implements a moving window integrator. Actually, mvwint() averages +* the signal values over the last WINDOW_WIDTH samples. +*****************************************************************************/ + +int mvwint(int datum, int init) + { + static long sum = 0 ; + static int data[WINDOW_WIDTH], ptr = 0 ; + int output; + if(init) + { + for(ptr = 0; ptr < WINDOW_WIDTH ; ++ptr) + data[ptr] = 0 ; + sum = 0 ; + ptr = 0 ; + } + sum += datum ; + sum -= data[ptr] ; + data[ptr] = datum ; + if(++ptr == WINDOW_WIDTH) + ptr = 0 ; + if((sum / WINDOW_WIDTH) > 32000) + output = 32000 ; + else + output = sum / WINDOW_WIDTH ; + return(output) ; + }