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

📄 perform.cpp

📁 信道仿真源代码
💻 CPP
字号:
///////////////////////////////////////////////////////
// Perform.cpp : implementation file
//
//  NOTE:: these functions depend on the 64 bit performance timer
// found in all Pentium processors. This timer may not be present
//  in some of the non-Intel versions.
//////////////////////////////////////////////////////////////////////
// Copyright 2000.    Moe Wheatley AE4JY  <ae4jy@mindspring.com>
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or any later version.
//
//This program 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "pathsim.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#ifdef TESTMODE
#include "Perform.h"

#define K_2PI ( 8.0 * atan(1.0) )		// 2 Pi
#define K_HIST_RES 500	

static double sum = 0.0;
static double rms = 0.0;
static int cnt = 0;
static BOOL delay = FALSE;
static FILE *stream = NULL;
static double timeinc = 0.0;
static INT HistArray[K_HIST_RES];
static double endfreq;
static double freqinc;

static double testfreq = -1.0;

double gDebug1 = 0.0;
double gDebug2 = 0.0;
INT iDebug3 = 0;

/////////////////////////////////////////////////////////////////////////////
static LONGLONG StartTime;
static LONGLONG StopTime;
static LONGLONG DeltaTime;
static LONGLONG CountFreq;
static LONGLONG DeltaTimeMax;
static LONGLONG DeltaTimeMin;
static LONGLONG DeltaTimeAve;
static LONGLONG DeltaSamples;


// call to initialize the prformance timer
void InitPerformance()
{
	QueryPerformanceFrequency( (LARGE_INTEGER*)&CountFreq );	//get clock freq
	DeltaTimeMax = 0;
	DeltaTimeAve = 0;
	DeltaSamples = 0;
	DeltaTimeMin = 0x7FFFFFFFFFFFFFFF;
}

// Starts the performance timer
void StartPerformance()
{
	QueryPerformanceCounter( (LARGE_INTEGER*)&StartTime );
}

// Stop performance timer and calculate timing values
void StopPerformance()
{
	QueryPerformanceCounter( (LARGE_INTEGER*)&StopTime );
	DeltaTime = StopTime-StartTime;
	DeltaTimeAve += DeltaTime;
	DeltaSamples++;
	if( DeltaTime>DeltaTimeMax )
		DeltaTimeMax = DeltaTime;
	if( DeltaTime<DeltaTimeMin )
		DeltaTimeMin = DeltaTime;

}

// Call this to measure time between succesive calls to SamplePerformance()
void SamplePerformance()
{
	if(	DeltaSamples == 0 )
	{
		QueryPerformanceCounter( (LARGE_INTEGER*)&StartTime );
	}
	else
	{
		QueryPerformanceCounter( (LARGE_INTEGER*)&StopTime );
		DeltaTime = StopTime-StartTime;
		DeltaTimeAve += DeltaTime;
		if( DeltaTime>DeltaTimeMax )
			DeltaTimeMax = DeltaTime;
		if( DeltaTime<DeltaTimeMin )
			DeltaTimeMin = DeltaTime;
		QueryPerformanceCounter( (LARGE_INTEGER*)&StartTime );
	}
	DeltaSamples++;
}

// output various timing statistics to Message Box
// DeltaTimeMax == maximum time between start()-stop() or sample()-Sample()
// DeltaTimeMin == minimum time between start()-stop() or sample()-Sample()
// DeltaTimeAve == average time between start()-stop() or sample()-Sample()
// DeltaSamples == number of time samples captured
void ReadPerformance()
{
char buf[200];
	if(DeltaSamples != 0 )
	{
		DeltaTime = (DeltaTime*1000000)/CountFreq;
		DeltaTimeMin = (DeltaTimeMin*1000000)/CountFreq;
		DeltaTimeMax = (DeltaTimeMax*1000000)/CountFreq;
		DeltaTimeAve = DeltaTimeAve/DeltaSamples;
		DeltaTimeAve = (DeltaTimeAve*1000000)/CountFreq;
		sprintf( buf, " Max=%I64u uSec Min=%I64u uSec\nAve=%I64u uSec #Samps=%I64u",
					DeltaTimeMax,DeltaTimeMin,DeltaTimeAve,DeltaSamples);
		AfxMessageBox( buf );
	}
}




/////////////////////////////////////////////////////////////////////////
//////  P a t h S i m   T e s t   B e n c h  R o u t i n e s ////////////
/////////////////////////////////////////////////////////////////////////

// Measure RMS power of complex sample over 'samplength' samples
//  from sweep generator.  Save results into a file.
void CalcCpxSweepRMS(_complex sample, INT samplength)
{
	if(testfreq<0.0)	//if first call then ignor this call
		return;
	if( delay )		//allow things to settle before starting sampling
	{
		if(++cnt >= samplength )
		{
			delay = FALSE;
			cnt = 0;
		}
	}
	else
	{
		sum = sum + ( sample.x*sample.x + sample.y*sample.y);
		if(++cnt >= samplength)
		{
			rms = sqrt(sum/(double)samplength);
			sum = 0.0;
			cnt = 0;
			delay = TRUE;		// delay one run to allow things to settle
			if(testfreq <= endfreq)
			{
				fprintf( stream, "%g, %g\n", testfreq, 20*log10(rms + 1e-100) );
				testfreq += freqinc;
				gDebug1 = rms;
				gDebug2 = testfreq;
			}
		}
	}
}
// Measure RMS power of real sample over 'samplength' samples
//  from sweep generator.  Save results into a file.
void CalcSweepRMS(double sample, INT samplength)
{
	if(testfreq<0.0)	//if first call then ignor this call
		return;
	if( delay )		//allow things to settle before starting sampling
	{
		if(++cnt >= samplength )
		{
			delay = FALSE;
			cnt = 0;
		}
	}
	else
	{
		sum = sum + (sample*sample);
		if(++cnt >= samplength)
		{
			rms = sqrt(sum/(double)samplength);
			sum = 0.0;
			cnt = 0;
			delay = TRUE;		// delay one run to allow things to settle
			if(testfreq <= endfreq)
			{
				fprintf( stream, "%g, %g\n", testfreq, 20*log10(rms) );
				testfreq += freqinc;
				gDebug1 = rms;
				gDebug2 = testfreq;
			}
		}
	}
}

// Measure phase angle of complex sinwave sample over 'samplength' samples
//  from sweep generator.  Save results into a file.
// Uses trig identity and assumes sinwave inputs of same frequency:
//  sin(a)sin(b) = 1/2 cos(a-b) - 1/2 cos(a+b)
// LP filter(average) the cos(a+b) term out and it leaves 1/2cos(phzedif)
//    then take inv cos to get angle.
void CalcCpxSweepPhz(_complex sample, INT samplength)
{
double mag;
	if(testfreq<0.0)	//if first call then ignor this call
		return;
	if( delay )		//allow things to settle before starting sampling
	{
		if(++cnt >= samplength )
		{
			delay = FALSE;
			cnt = 0;
		}
	}
	else
	{	//normalize amplitude.
		mag = (sample.x*sample.x+sample.y*sample.y);
		sum = sum + sample.x*sample.y/mag;	//add sin(a)*sin(b) term
		if(++cnt >= samplength)
		{
			rms = 360.0*acos(2*sum/(double)samplength)/K_2PI; //convert to angle
			sum = 0.0;
			cnt = 0;
			delay = TRUE;		// delay one run to allow things to settle
			if(testfreq <= endfreq)
			{
				fprintf( stream, "%g, %g\n", testfreq, rms);
				testfreq += freqinc;
				gDebug1 = rms;
				gDebug2 = testfreq;
			}
		}
	}
}

// Generate a RMS=1 real sinwave sweep frequency from start to stop
//   with given sample rate and step size.
void SweepGen(  double* output, double samprate, 
							double start, double stop, double step )
{
	if(testfreq<0.0)	//if first call then initialize everything
	{
		timeinc = 0.0;
		testfreq = start;
		endfreq = stop;
		freqinc = step;
		sum = 0.0;
		rms = 0.0;
		cnt = 0;
		delay = TRUE;		// delay one run to allow things to settle
		stream = fopen( "c:\\Data.prn", "wt" );	//Open file for write
	}
	*output = 1.414213562*sin(timeinc);
	timeinc += ( (K_2PI/samprate)*testfreq);
	timeinc = fmod(timeinc,K_2PI);	//keep radian counter bounded
}
// Generate a RMS=1 complex sinwave sweep frequency from start to stop
//   with given sample rate and step size.
void SweepGenCpx(  _complex* output, double samprate, 
							double start, double stop, double step )
{
	if(testfreq<0.0)	//if first call then initialize everything
	{
		timeinc = 0.0;
		testfreq = start;
		endfreq = stop;
		freqinc = step;
		sum = 0.0;
		rms = 0.0;
		delay = TRUE;		// delay one run to allow things to settle
		cnt = 0;
		stream = fopen( "c:\\Data.prn", "wt" );	//Open file for write
	}
	output->x = cos(timeinc);
	output->y = sin(timeinc);
	timeinc += ( (K_2PI/samprate)*testfreq);
	timeinc = fmod(timeinc,K_2PI);	//keep radian counter bounded
}


void HistogramSamp(  double sample, double min, double max, INT numsamps )
{
double K;
INT i;
INT hmax;
	if(!delay)	//if first call then initialize everything
	{
		cnt = 0;
		delay = TRUE;		// delay one run to allow things to settle
		stream = fopen( "c:\\Data.prn", "wt" );	//Open file for write
		for(i=0;i<K_HIST_RES; i++)
			HistArray[i] = 0;
	}
	if(cnt < numsamps)
	{
		K = (K_HIST_RES-1)/(max-min);
		i = (INT)( K*(sample-min) );
		if( i>0 && i <K_HIST_RES)
			HistArray[i]++;
		cnt++;
		gDebug1 = (double)cnt;
	}
	if(cnt == numsamps)
	{
		hmax = 0;
		for(i=0;i<K_HIST_RES; i++)
		{
			if( HistArray[i] > hmax)
				hmax = HistArray[i];
		}
		for(i=0;i<K_HIST_RES; i++)
		{
			K = (double)i*(max-min)/(double)K_HIST_RES + min;
			fprintf( stream, "%g, %g\n", K,
							(double)HistArray[i]/(double)hmax);
		}
		cnt++; 
	}
	
}

//call this to end the test and close the data file if open;
void EndTest(void)
{
	delay = FALSE;
	timeinc = 0.0;
	testfreq = -1.0;
	if(stream)
		fclose( stream );
}

///////////////////////////////////////////////////////////////////
//calculates RMS value of complex sample over numsamps
//  called once for each sample being measured
///////////////////////////////////////////////////////////////////
double CalcCpxRMS(_complex sample, INT numsamps)
{
static double sum = 0.0;
static double rms = 0.0;
	sum = sum + ( sample.x*sample.x + sample.y*sample.y);
	if(++cnt >= numsamps)
	{
		rms = sqrt(sum/(double)numsamps);
		sum = 0.0;
		cnt = 0;
	}
	return rms;
}

///////////////////////////////////////////////////////////////////
//calculates running average RMS value of buf[] samples
//  called once for each buffer to be measured
///////////////////////////////////////////////////////////////////
double CalcRunAveRMS(double* buf, INT bufsize)
{
#define RMSBAVE 1000
static double sum = 0.0;
static double rms = 0.0;
	sum = 0.0;
	for( INT i = 0; i<bufsize; i++)
		sum = sum + ( buf[i]*buf[i] );
	rms = (1.0/RMSBAVE)*sqrt(sum/bufsize) + (1.0-1.0/RMSBAVE)*rms;
	return rms;
}

///////////////////////////////////////////////////////////////////
//calculates running average RMS value of buf[] complex samples
//  called once for each buffer to be measured
///////////////////////////////////////////////////////////////////
double CalcCpxRunAveRMS(_complex* buf, INT bufsize)
{
#define RMSCPXAVE 300
static double sum = 0.0;
static double rms = 0.0;
	for( INT i = 0; i<bufsize; i++)
		sum = sum + ( buf[i].x*buf[i].x +  buf[i].y*buf[i].y);
	rms = (1.0/RMSCPXAVE)*sqrt(sum/bufsize) + (1.0-1.0/RMSCPXAVE)*rms;
	sum = 0.0;
	return rms;
}

///////////////////////////////////////////////////////////////////
//calculates RMS value of buf[] samples over RMS_SIZE*numsamps
//  called once for each buffer to be measured
///////////////////////////////////////////////////////////////////
double CalcTotalRMS(double* buf, INT numsamps)
{
#define RMS_SIZE 7000	//abt 30 minutes at 8000 KSP
static double sum = 0.0;
static int cnt = 0;
static double rms = 0.0;
	for( INT i = 0; i<numsamps; i++)
		sum = sum + ( buf[i]*buf[i] );
	if( ++cnt >= RMS_SIZE)
	{
		rms = sqrt(sum/(cnt*numsamps));
		sum = 0.0;
		cnt = 0;
	}
	return rms;
}


#endif //TESTMODE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -