📄 coarse_delay_est.cpp
字号:
//
// File = coarse_delay_est.cpp
//
#include <stdlib.h>
#include <complex>
#include "parmfile.h"
#include "coarse_delay_est.h"
#include "misdefs.h"
#include "model_graph.h"
#include "dit_pino_T.h"
#include "dit_nipo_T.h"
extern ParmFile* ParmInput;
extern int PassNumber;
#ifdef _DEBUG
extern ofstream *DebugFile;
#endif
//======================================================
CoarseDelayEstimator::CoarseDelayEstimator( char* instance_name,
PracSimModel* outer_model,
Signal<float>* in_sig,
Signal<float>* ref_sig,
Signal<float>* out_sig,
Control<bool>* dly_est_is_valid_cntl,
Control<float>* delay_at_max_corr,
Control<int>* samps_delay_at_max_corr)
:PracSimModel(instance_name,
outer_model)
{
In_Sig = in_sig;
Ref_Sig = ref_sig;
Out_Sig = out_sig;
Delay_At_Max_Corr = delay_at_max_corr;
Samps_Delay_At_Max_Corr = samps_delay_at_max_corr;
Dly_Est_Is_Valid_Cntl = dly_est_is_valid_cntl;
Dly_Est_Is_Valid_Cntl->SetValue(false);
OPEN_PARM_BLOCK;
GET_INT_PARM(Num_Corr_Passes);
GET_BOOL_PARM(Limited_Search_Window_Enab);
if(Limited_Search_Window_Enab)
{
GET_INT_PARM(Search_Window_Beg);
GET_INT_PARM(Search_Window_End);
}
GET_BOOL_PARM(Invert_Input_Sig_Enab);
GET_INT_PARM(Smoothing_Sidelobe_Len);
MAKE_OUTPUT(Out_Sig);
MAKE_INPUT(In_Sig);
MAKE_INPUT(Ref_Sig);
SAME_RATE(In_Sig, Out_Sig);
SAME_RATE(Ref_Sig, Out_Sig);
Spectrum_File = new ofstream("spectrum.txt\0", ios::out);
}
//======================================================
CoarseDelayEstimator::~CoarseDelayEstimator( void ){ };
//======================================================
void CoarseDelayEstimator::Initialize(void)
{
int dummy_size, i;
double tmp_nsexp;
double frac_part, int_part;
float sample=0;
Proc_Block_Size = Out_Sig->GetBlockSize();
Samp_Intvl = Out_Sig->GetSampIntvl();
In_Sig_Buf = new AuxSignalBuffer<float>(sample, Proc_Block_Size);
Ref_Sig_Buf = new AuxSignalBuffer<float>(sample, Proc_Block_Size);
tmp_nsexp = log10(double(Proc_Block_Size))/log10(2.0);
frac_part = modf(tmp_nsexp, &int_part);
if( frac_part != 0.0 )
{
Ns_Exp = int_part + 2;
}
else
{
Ns_Exp = int_part + 1;
}
Full_Corr_Size = pow(2.0, Ns_Exp);
X = new std::complex<float>[Full_Corr_Size];
Y = new std::complex<float>[Full_Corr_Size];
if(Limited_Search_Window_Enab)
{
if(Search_Window_Beg < 0)
{
Neg_Window_Beg = Full_Corr_Size + Search_Window_Beg;
Pos_Window_Beg = 0;
}
else
{
Neg_Window_Beg = Full_Corr_Size;
Pos_Window_Beg = Search_Window_Beg;
}
if(Search_Window_End >= 0)
{
Pos_Window_End = Search_Window_End;
Neg_Window_End = Full_Corr_Size-1;
}
else
{
Pos_Window_End = -1;
Neg_Window_End = Search_Window_End;
}
}
else
{
Neg_Window_Beg = Full_Corr_Size/2 + 1;
Neg_Window_End = Full_Corr_Size-1;
Pos_Window_Beg = 0;
Pos_Window_End = Full_Corr_Size/2 - 1;
}
dummy_size = Full_Corr_Size - Proc_Block_Size;
Zero_Array = new std::complex<float>[dummy_size];
for( i = 0; i < dummy_size; i++)
{
Zero_Array[i] = std::complex<float>(0.0, 0.0);
}
Size_Of_FComplex = sizeof(std::complex<float>);
Max_Corr = 0.0;
Max_Corr_Time = 0.0;
Diff_Response = new std::complex<float>[Full_Corr_Size];
for( i=0; i<Full_Corr_Size; i++)
{
Diff_Response[i] = 0.0;
}
Corr_Pass_Count = 0;
return;
}
//======================================================
int CoarseDelayEstimator::Execute()
{
using std::complex;
float *in_sig_ptr, *in_sig_buf_ptr;
float *ref_sig_ptr, *ref_sig_buf_ptr;
int in_sig_buf_count;
int ref_sig_buf_count;
float *out_sig_ptr;
float max_corr;
float out_mag, x_temp; // out_angle;
float max_corr_time;
int zero_size;
int samp, max_samp;
double deg_per_rad = 180.0/PI;
double phase_deg;
if(Corr_Pass_Count > Num_Corr_Passes) return(_MES_AOK);
//-------------------------------------------------------
// Copy frequently accessed member vars into local vars
std::complex<float> *x = X;
std::complex<float> *y = Y;
int proc_block_size;
int in_sig_block_size;
int ref_sig_block_size;
int full_corr_size = Full_Corr_Size;
int size_of_fcomplex = Size_Of_FComplex;
int ns_exp = int(Ns_Exp);
int smoothing_sidelobe_len = Smoothing_Sidelobe_Len;
double samp_intvl = Samp_Intvl;
double phase_to_time;
double phase_rad;
double tau, tau_sum, tau_avg;
double denom, numer;
int regression_start, regression_stop;
double phase_sum;
double phase_avg;
double idx_sum, idx_avg;
std::complex<float> x_of_f[4096];
bool phase_has_wrapped;
float amp;
//---------------------------------------------------
// Get pointers for input and output
in_sig_ptr = GET_INPUT_PTR(In_Sig);
ref_sig_ptr = GET_INPUT_PTR(Ref_Sig);
out_sig_ptr = GET_OUTPUT_PTR(Out_Sig);
proc_block_size = Proc_Block_Size;
in_sig_block_size = In_Sig->GetValidBlockSize();
ref_sig_block_size = Ref_Sig->GetValidBlockSize();
//---------------------------------------------------
// Check to see if there enough samples of input
// signal and reference signal to perform correlation
// If not, set valid block size for output to zero
// and then exit from this model.
in_sig_buf_ptr = In_Sig_Buf->Load( in_sig_ptr,
in_sig_block_size,
&in_sig_buf_count);
ref_sig_buf_ptr = Ref_Sig_Buf->Load(ref_sig_ptr,
ref_sig_block_size,
&ref_sig_buf_count);
if( (in_sig_buf_count < proc_block_size)
|| (ref_sig_buf_count < proc_block_size))
{
Out_Sig->SetValidBlockSize(0);
return(_MES_AOK);
}
//----------------------------------------
zero_size = full_corr_size - proc_block_size;
phase_to_time = full_corr_size * samp_intvl/TWO_PI;
int i;
for( i=0; i<proc_block_size; i++){
x[i] = std::complex<float>( *in_sig_buf_ptr++, 0.0 );
}
In_Sig_Buf->Release(proc_block_size);
for( i=proc_block_size; i<full_corr_size; i++){
x[i] = 0.0;
}
if(Invert_Input_Sig_Enab){
for( i=0; i<proc_block_size; i++){
x[i] = -x[i];
}
}
for( i=0; i<proc_block_size; i++){
y[i] = std::complex<float>( *ref_sig_buf_ptr++, 0.0 );
}
Ref_Sig_Buf->Release(proc_block_size);
for( i=proc_block_size; i<full_corr_size; i++){
y[i] = 0.0;
}
FftDitNipo<float>(x, full_corr_size);
FftDitNipo<float>(y, full_corr_size);
// perform correlation
for(samp=0; samp < full_corr_size; samp++){
//x[samp] /= float(full_corr_size);
x[samp] *= std::conj<float>( y[samp] ) / float(full_corr_size);
}
//----------------------------------------------------------
if( (PassNumber >= 2) &&
(Corr_Pass_Count <= Num_Corr_Passes) ){
tau_sum = 0.0;
tau_avg = 0.0;
phase_has_wrapped = false;
for(samp=0; samp < full_corr_size; samp++){
Diff_Response[samp] += x[samp];
if(Corr_Pass_Count == Num_Corr_Passes){
amp = std::abs<float>(Diff_Response[samp]);
phase_deg = deg_per_rad * std::arg<float>(Diff_Response[samp]);
if(phase_deg > 100) phase_has_wrapped = true;
if( !phase_has_wrapped) regression_stop = samp;
phase_rad = PI * phase_deg/180.0;
tau = 0.0;
if(samp !=0)
{
tau = -phase_to_time * phase_rad/samp;
}
(*Spectrum_File) << samp << ", " << amp << ", "
<< phase_deg << ", "
<< tau << endl;
}
}
if(Corr_Pass_Count == Num_Corr_Passes){
regression_start = 5;
if(regression_stop > 300) regression_stop = 300;
phase_sum = 0.0;
idx_sum = 0.0;
for(samp=regression_start; samp < regression_stop; samp++){
phase_rad = std::arg<float>(Diff_Response[samp]);
phase_sum += phase_rad;
idx_sum += samp;
}
numer = 0.0;
denom = 0.0;
idx_avg = idx_sum / (regression_stop - regression_start);
phase_avg = phase_sum / (regression_stop - regression_start);
for(samp=regression_start; samp < regression_stop; samp++){
phase_rad = std::arg<float>(Diff_Response[samp]);
numer += (samp-idx_avg)*(phase_rad - phase_avg);
denom += (samp-idx_avg)*(samp-idx_avg);
}
tau = -phase_to_time * numer / denom;
Spectrum_File->close();
}
Corr_Pass_Count++;
}
//----------------------------------------------------
IfftDitPino<float>(x, full_corr_size);
// fill the output buffer
//memcpy( out_sig_ptr, x, proc_block_size*size_of_fcomplex);
for(int ii=0; ii<proc_block_size; ii++){
out_sig_ptr[ii] = x[ii].real();
}
// Determine maximum correlation plus corresponding time
out_mag = 0.0;
for(samp=Neg_Window_Beg; samp <= Neg_Window_End; samp++){
x_temp = x[samp].real();
(*DebugFile) << samp << ", " << x_temp << endl;
if( x_temp > out_mag)
{
out_mag = x_temp;
max_corr = x[samp].real();
max_samp = samp;
}
}
for(samp=Pos_Window_Beg; samp <= Pos_Window_End; samp++)
{
x_temp = x[samp].real();
(*DebugFile) << samp << ", " << x_temp << endl;
if( x_temp > out_mag)
{
out_mag = x_temp;
max_corr = x[samp].real();
max_samp = samp;
}
}
(*DebugFile) << "max_samp = " << max_samp << endl;
if( max_samp > proc_block_size ) max_samp -= full_corr_size;
max_corr_time = max_samp*samp_intvl;
// if( (fabs(max_corr) < 1.0e-30) )
// {
// max_corr = 1.0;
// }
Delay_At_Max_Corr->SetValue(max_corr_time);
#ifdef _DEBUG
(*DebugFile) << "Correlator found delay as " << max_corr_time << endl;
#endif
Samps_Delay_At_Max_Corr->SetValue(max_samp);
Dly_Est_Is_Valid_Cntl->SetValue(true);
//---------------------
return(_MES_AOK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -