📄 resp.c
字号:
#include "comuse.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
////////////////////////////////////////////////////////////////////////////////
int SAMPLE_RATE=125;
//#define SAMPLE_RATE 125 //8ms调用一次所以是125
#define CALPERIOD 2000 //最小是15/分的呼吸波,4秒一个波形,4秒500个点,2000个点16秒,4个波形
int resp_rate=0;
int iCalCnt=0;
void calculate(int Restdata) //
{
// constant definitions
#define INIT_VALIDDIRLEN 8 // initial ValidDirCheckLen(Rising/Falling enough length)
#define INIT_MAXDISTURBLEN 2 // initial Maximum disturb length
#define RESET_PERIOD 30 // Timer in Second for no valid Reset found reset
#define VALIDDIRLEN_PROP 8 // Properation of ValidDirectCheckLen as RespPeriod
#define MIN_VALIDDIRLEN 2 // Minimum ValidDirCheckLen for disturb tolerence //
#define MAX_VALIDDIRLEN 40 // Minimum ValidDirCheckLen for MaxRespRate find //
#define MAXDISTLEN_PROP 4 // Properation of MaxDisturbLen as ValidDirectCheckLen
#define MIN_MAXDISTLEN 1 // Minimum MaxDisturbLen //
#define INIT_RESPPERIOD 300 // Init Resp Period(for RespRate=15 at 80hz sample rate) 有问题,采样率是125应该是500次一个呼吸周期(resprate=15)
#define INIT_DIR_LEN 2 // minimum length of first Rising/Falling
// disturb ___means Falling/Rising while count the length of Rising/Falling
// if define this constant,the discret disturb will all be counted
// else only continous disturb will be counted
//#define DISCRET_DISTURB 1
// define this constant for running in Windows enviroment
//#define RUN_IN_WINDOWS 1
// define this constant if want a mark to be drawn on key pos
//#define DRAW_MARK 1
static short ValidDirLenUp = INIT_VALIDDIRLEN; // up threthold of sucessive Rising/Falling length
static short MaxDisturbLen = INIT_MAXDISTURBLEN; // up threthold of sucessive disturb length
static short ProcStage = 0; // process stage counter
static unsigned short BegRisingPos = 0; // first(initial) Rising position
static unsigned short SecondRisingPos; // Second(after valid length of falling) Rising position
static unsigned short PeriodCnt = 0; // counter for remember the postion
static unsigned short PeriodAveragePos = 0; // begin pos of PeriodAverage
static short RisingCount = 0; // Sucessive Rising length counter
static short FallingCount = 0; // Sucessive Falling length counter
static short LearnOver = 0; // flag for any valid peak found
static unsigned long PeriodAverage = 0; // average of every period for checking of SecondRising validity
static unsigned long PeriodAverageRn = 0; // average of every rising renew the PeriodAvarege
static short LastData = 128;
short Data = Restdata; // the current sample data
//#if !defined RUN_IN_WINDOWS
//#define DRAW_SMP_RATE 4
// static short DrawCount = DRAW_SMP_RATE;
//#define SAMPLE_RATE 82
//#endif
static short ResetCnt = 0; // Process reset WatchDog timer counter
static short CntRespPeriod = INIT_RESPPERIOD; // current found RespPeriod
static short LastRespPeriod = INIT_RESPPERIOD; // Last found RespPeriod
static short PeriodAcc = 0; // Accumulate of RespPeriod when not accept
static short PeriodAccCnt = 0; // Count of RespPeriodACC when not accept
#define WEIGHT_ACC_LEN 12 // up limit of PeriodAcc length that will be accept
static short Weight[4]={WEIGHT_ACC_LEN,6,3,2};
static short WeightAcc = 0;
#define MIN_RESPRATE 3
#define MAX_RESPRATE 120
if(iCalCnt++>=CALPERIOD)
iCalCnt=0;
PeriodCnt++;
if( PeriodCnt == 0 )
{
PeriodCnt = (BegRisingPos < SecondRisingPos) ? BegRisingPos : SecondRisingPos; //取小的
PeriodCnt = (PeriodCnt < PeriodAveragePos) ? PeriodCnt : PeriodAveragePos;
BegRisingPos -= PeriodCnt; //从PeriodCnt开始记一个新的周期
SecondRisingPos -= PeriodCnt;
PeriodAveragePos -= (PeriodCnt-1);
PeriodCnt = 0-PeriodCnt;
}
// If the time period of no valid resp found more than given period,reset the
// process to learning again
ResetCnt++;
if( LearnOver && ResetCnt>RESET_PERIOD*SAMPLE_RATE )
{
ProcStage = 0;
ValidDirLenUp = INIT_VALIDDIRLEN; //8
MaxDisturbLen = INIT_MAXDISTURBLEN; //2
ResetCnt = 0;
PeriodCnt = 1;
LearnOver = 0;
RisingCount = 0;
FallingCount = 0;
CntRespPeriod = INIT_RESPPERIOD; // current found RespPeriod=300
LastRespPeriod = INIT_RESPPERIOD; // Last found RespPeriod=300
PeriodAveragePos = 0;
PeriodAverage = 0;
#if !defined RUN_IN_WINDOWS
resp_rate = -1; // for indicator of no RespRate detected
#endif
}
Data = (Data+LastData+1)/2; // average with roundup
PeriodAverage += Data;
if(ProcStage==0)
{
if( Data > LastData )
{
RisingCount++;
if( RisingCount == INIT_DIR_LEN ) //INIT_DIR_LEN =2
{
BegRisingPos = PeriodCnt; //上升沿起始位置1
ProcStage++;
RisingCount = 0; //上升沿计数清零
FallingCount = 0; //下降沿计数清零
}
}
else if( Data < LastData ) RisingCount = 0; //找上升沿起始位置
}
else if(ProcStage==1)
{
if( Data >= LastData )
{
RisingCount++;
if( RisingCount > ValidDirLenUp ) //ValidDirLenUp=8
{
ProcStage++;
RisingCount = 0; //如果找到8个连续的上升就认为找到上升沿了
FallingCount = 0;
}
//#if defined DISCRET_DISTURB
// if( Data > LastData ) FallingCount = 0;
//#else
FallingCount = 0;
//#endif
}
else if( Data < LastData ) //如果有两个连续的 下降沿就说明有干扰,重新开始算
{
FallingCount++;
if( FallingCount > MaxDisturbLen )
{
ProcStage = 0;
ValidDirLenUp = INIT_VALIDDIRLEN; //8
MaxDisturbLen = INIT_MAXDISTURBLEN; //2
ResetCnt = 0;
PeriodCnt = 0;
LearnOver = 0;
RisingCount = 0;
FallingCount = 0;
CntRespPeriod = INIT_RESPPERIOD; // current found RespPeriod
LastRespPeriod = INIT_RESPPERIOD; // Last found RespPeriod
PeriodAveragePos = 0;
PeriodAverage = 0;
#if !defined RUN_IN_WINDOWS
resp_rate = -1; // for indicator of no RespRate detected
#endif
}
}
}
if(ProcStage==2) //找下降沿
{
if( Data < LastData )
{
FallingCount++;
if( FallingCount == INIT_DIR_LEN ) //如果发现连续2个下降沿就进入procstage3
{
ProcStage++;
FallingCount = 0;
RisingCount = 0;
}
}
else if( Data > LastData ) FallingCount = 0;
}
else if(ProcStage==3)
{
if( Data <= LastData )
{
FallingCount++;
if( FallingCount > ValidDirLenUp ) //如果有8个连续的下降沿 说明找到下降沿了
{
ProcStage++; //进入procstage4
RisingCount = 0;
FallingCount = 0;
}
//#if defined DISCRET_DISTURB
// if( Data < LastData ) RisingCount = 0;
//#else
RisingCount = 0;
//#endif
}
else if( Data > LastData )
{
RisingCount++;
if( RisingCount > MaxDisturbLen ) ProcStage = 2; //如果有上升沿的干扰,那么重新开始找下降沿
}
}
else if(ProcStage==4) //找第二个上升沿
{
if( Data > LastData )
{
RisingCount++;
if( RisingCount == INIT_DIR_LEN ) // 如果连续2个上升沿且不大于平均值
{ // if the Second Rising pos is above average,invalid
if( Data <= (int)(PeriodAverage/(PeriodCnt-PeriodAveragePos)) )
{
SecondRisingPos = PeriodCnt;
PeriodAverageRn = PeriodAverage; // remeber the begin of Re-Average
ProcStage++;
RisingCount = 0;
FallingCount = 0;
}
else
RisingCount = 0;
}
}
else if( Data < LastData ) RisingCount = 0;
}
else if(ProcStage==5)
{
if( Data >= LastData )
{
RisingCount++;
if( RisingCount > ValidDirLenUp ) //连续发现8个上升沿
{
CntRespPeriod = SecondRisingPos-BegRisingPos; //计算CntRespPeriod
FallingCount = 0;
RisingCount = 0;
// a valid wave peak found and to calculate the RespRate
// to check its validity
if( LearnOver ) // valid check only when any valid found before
{ // for RespRate<MIN_RESPRATE,To find initial Rising
if( CntRespPeriod >= 60*SAMPLE_RATE/MIN_RESPRATE )
{
ProcStage = 0;
ValidDirLenUp = INIT_VALIDDIRLEN;
MaxDisturbLen = INIT_MAXDISTURBLEN;
ResetCnt = 0;
PeriodCnt = 0;
LearnOver = 0;
RisingCount = 0;
FallingCount = 0;
CntRespPeriod = INIT_RESPPERIOD; // current found RespPeriod
LastRespPeriod = INIT_RESPPERIOD; // Last found RespPeriod
PeriodAveragePos = 0;
PeriodAverage = 0;
#if !defined RUN_IN_WINDOWS
resp_rate = -1; // for indicator of no RespRate detected
#endif
return;
}
// for RespRate>MAX_RESPRATE,Continue to find new Rising after enough falling
else if( CntRespPeriod <= 60*SAMPLE_RATE/MAX_RESPRATE)
{
ProcStage = 4;
return;
}
else
{
int WeightIndex;
ResetCnt = 0;
PeriodAcc +=CntRespPeriod;
PeriodAccCnt++;
if( CntRespPeriod>LastRespPeriod )
{
WeightIndex = (2*CntRespPeriod-LastRespPeriod)/(2*LastRespPeriod);
}
else
{
WeightIndex = 4*(LastRespPeriod-CntRespPeriod)/LastRespPeriod;
}
BegRisingPos = SecondRisingPos;
PeriodAveragePos = SecondRisingPos;
PeriodAverage -= PeriodAverageRn;
WeightAcc += Weight[WeightIndex];
if( WeightAcc < WEIGHT_ACC_LEN )
{ // research from Stage2
ProcStage = 2; // (To find Falling)
return;
}
CntRespPeriod = PeriodAcc/PeriodAccCnt;
LastRespPeriod = (CntRespPeriod+LastRespPeriod+1)/2;
}
}
// for LeasrnOver = 0,accept the Period directly
else
{
LastRespPeriod = CntRespPeriod;
LearnOver = 1;
}
PeriodAcc = 0;
PeriodAccCnt = 0;
WeightAcc = 0;
// renew the deciding limit
ValidDirLenUp = LastRespPeriod/VALIDDIRLEN_PROP;
if( ValidDirLenUp < MIN_VALIDDIRLEN ) ValidDirLenUp = MIN_VALIDDIRLEN;
if( ValidDirLenUp > MAX_VALIDDIRLEN ) ValidDirLenUp = MAX_VALIDDIRLEN;
MaxDisturbLen = ValidDirLenUp/MAXDISTLEN_PROP;
if( MaxDisturbLen < MIN_MAXDISTLEN ) MaxDisturbLen = MIN_MAXDISTLEN;
ProcStage = 2; // (To find Falling)
resp_rate = (60*SAMPLE_RATE+LastRespPeriod/2)/LastRespPeriod;
//if(bSampleRT200==1)resp_rate=resp_rate-(resp_rate/5);//(resp_rate<<2)/5;
}
//#if defined DISCRET_DISTURB
// if( Data > LastData ) FallingCount = 0;
//#else
FallingCount = 0;
//#endif
}
else if( Data < LastData )
{
FallingCount++;
if( FallingCount > MaxDisturbLen ) ProcStage = 4;
}
}
LastData = Data;
}
////////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -