⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resp.c

📁 采用呼吸阻抗法
💻 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 + -