📄 midamble_rcv.c
字号:
// TODO: Use this Nicolae-function over all possible indexes // giving peak_amp[0]..peak_amp[max_index-1] { //int re, im, sq; peak_amp = 0; stats_offset = 0; mid_amp_old =0; for ( i=0; i<private->est.estimation_length; i++ ) { re = est->matched_filter_Re[i]; im = est->matched_filter_Im[i]; sq = re * re + im * im; mid_amp_old +=sq; if ( sq > peak_amp ) { peak_amp = sq; stats_offset = i; com_p.real = re; com_p.imag = im; } private->mafi[i].real = re; private->mafi[i].imag = im; } } peak_amp = sqrt( peak_amp ); /* // TODO: print all amplitudes // define peak_amp as array of integer and define max_index // Put peak_amp as array of integer into the stats PR_DBG( 4, "Amplitudes for the indexes: " ); for ( i=0; i<max_index; i++ ){ PR_DBG_CL( 4, "peak_amp[%i]=%i ", i, peak_amp[i] ); } PR_DBG( 4, "Peak_Amp: %i, offset: %i, data_len: %i:%i, data_pos: %i:%i, est:%i\n", peak_amp, stats_offset, data_len_half, data_len_half, data_pos[0], data_pos[1], est->estimation_length ); */ // Matched filtering on the data is only done for the // index given in the configuration // Now extract symbols from data fields using matched filters // beginning of the first data field data_pos[0] = 0; // beginning of the second data field data_pos[1] = ( slc + mid_length ) / 2; // is the length of the 1st and 2nd data field data_len_half = ( slc - mid_length ) / 2; x += data_pos[0]; matched_filtering(x, (mmx_t*)est->matched_filter_Re, (mmx_t*)est->matched_filter_Im, out, est->estimation_length, DAQ_SAMPLES_PER_CHIP, data_len_half ); x += data_pos[1] - data_pos[0]; matched_filtering(x, (mmx_t *)est->matched_filter_Re, (mmx_t *)est->matched_filter_Im, &out[data_len_half], est->estimation_length, DAQ_SAMPLES_PER_CHIP, data_len_half ); // Filter the midamble mid_rx=swr_malloc(mid_length*sizeof(SYMBOL_COMPLEX)); mid_tx=swr_malloc(mid_length*sizeof(SYMBOL_COMPLEX)); x += mid_start - data_pos[1] - m->shift; matched_filtering(x, (mmx_t *)est->matched_filter_Re, (mmx_t *)est->matched_filter_Im, mid_rx, est->estimation_length, DAQ_SAMPLES_PER_CHIP, mid_length ); // Take the mean midamble-amplitude memset( private->midamble, 0, sizeof( private->midamble ) ); midamble_write( type, mid_tx, 1, index ); tmp = 0.; for(i=0; i<mid_length; i++) { tmp += (int)mid_rx[i].real * (int)mid_tx[i].real + (int)mid_rx[i].imag * (int)mid_tx[i].imag; private->midamble[i] = mid_rx[i]; } if ( tmp >= mid_length ) { mid_amp = (int)( tmp / mid_length ); } else { PR_DBG( 2, "tmp < mid_length: %s%i.%i\n", swr_ftosii( tmp ) ); for(i=0; i<mid_length; i++) { PR_DBG( 4, "%6i,%6i\n", (int)mid_rx[i].real * (int)mid_tx[i].real, (int)mid_rx[i].imag * (int)mid_tx[i].imag ); } mid_amp = 1; } midamble_write( type, mid_tx, mid_amp, index ); // Calculate the variance noise_var = 0.; mean_re = mean_im = 0; flip_prob = 0.0; for(i=0; i<mid_length; i++) { int re, im; re = mid_rx[i].real - mid_tx[i].real; im = mid_rx[i].imag - mid_tx[i].imag; mean_re += re; mean_im += im; noise_var += re * re + im * im; if(mid_rx[i].real * mid_tx[i].real < 0) flip_prob ++; if(mid_rx[i].imag * mid_tx[i].imag < 0) flip_prob ++; } noise_var /= mid_length; // Calculate the variance the old way // The number 82252 relates the midamble_amplitude to the energy // of the matched-filter. As this number is composed of the factors // noise, A/D resolution and length of the matched filter, it is // only correct for a certain SNR value. Especially for low SNR this // number is completely bogus! mid_amp_old /= 82252; noise_var_old = 0.; midamble_write( type, mid_tx, mid_amp_old, index ); for(i=0; i<mid_length; i++) { int re, im; re = mid_rx[i].real - mid_tx[i].real; im = mid_rx[i].imag - mid_tx[i].imag; noise_var_old += re * re + im * im; } noise_var_old /= mid_length; flip_prob /= (2 * mid_length); mean_re /= mid_length; mean_im /= mid_length; PR_DBG( 4, "len: %i, mid_amp:%i, peak:%5i, " "n_var:%s%i.%i, mean_re:%i, mean_im:%i, flip_prob:%f\n", private->est.estimation_length, mid_amp, peak_amp, swr_ftosii( noise_var ), mean_re, mean_im, flip_prob ); for(i=0; i<2; i++) { PR_DBG(4, "mid_tx[%2i]=(%6i,%6i) mid_rx[%2i]=(%6i,%6i) out[%2i]=(%6i,%6i)\n", i, mid_tx[i].real, mid_tx[i].imag, i, mid_rx[i].real, mid_rx[i].imag, i, out[i].real, out[i].imag ); } swr_free( mid_rx ); swr_free( mid_tx ); // Calculate the snr_data data_amp = 0.; for ( i=0; i < 2 * data_len_half; i++ ){ data_amp += out[i].real * out[i].real + out[i].imag * out[i].imag; } data_amp /= 2 * data_len_half; // And save the statistic parameters. swr_sdb_get_stats_struct( context->id, (void**)&stats ); stats->peak = com_p; stats->peak_amp = peak_amp; stats->mid_amp = mid_amp; stats->noise_var = noise_var; stats->flip_prob = max( flip_prob, (double)1e-3 ); stats->midamble.size = mid_length; if ( ( mid_amp <= 0 ) || ( noise_var <= 0 ) ) { PR_DBG( 2*0, "mid_amp: %i, noise_var: %s%i.%i\n", mid_amp, swr_ftosii( noise_var ) ); } else { stats->snr_mid = stats->snr = 10 * ( log10( mid_amp )*2 - log10( noise_var ) ); } if ( ( data_amp <= 0 ) || ( noise_var <= 0 ) || ( data_amp / noise_var - 1 <= 0 ) ) { PR_DBG( 2, "data_amp: %s%i.%i, noise_var: %s%i.%i\n", swr_ftosii( data_amp ), swr_ftosii( noise_var ) ); stats->snr = 0; } else { stats->snr_data = 10 * ( log10( data_amp / noise_var - 1 ) ); } // This is the old way of calculating the midamble-amplitude and the snr stats->noise_var_old = noise_var_old; stats->mid_amp_old = mid_amp_old; if ( ( mid_amp_old <= 0 ) || ( noise_var_old <= 0 ) ) { PR_DBG( 2, "mid_amp_old: %i, noise_var_old: %s%i.%i\n", mid_amp_old, swr_ftosii( noise_var_old ) ); } else { stats->snr_old = 10 * ( log10( mid_amp_old )*2 - log10( noise_var_old ) ); } if ( private->gain_control ) { if ( peak_amp < private->gain_control ) { //private->rx_gain += max( 1, ( private->gain_control - peak_amp ) / 10 ); private->rx_gain += 1; swr_ant_set_gain_rx( private->antenna, private->rx_gain ); } else { private->rx_gain -= 1; swr_ant_set_gain_rx( private->antenna, private->rx_gain ); } } for (i = 0; i < MAX_CH_EST; i++) { stats->peak_amp_stat[i] = private->peak_amp_stat[i]; } swr_sdb_get_config_struct( context->id, (void**)&config ); // This offset can be added directly to the 'final' offset stats->offset = ( stats_offset - config->peak_location ) / 4; swr_sdb_free_config_struct( context->id, (void**)&config ); swr_sdb_free_stats_struct( context->id, (void**)&stats ); PR_DBG( 4, "Exiting\n" ); return(0);}/* * This is the `destructor'. */int rcv_finalize( swr_sdb_t *context ) { stats_t *stats; swr_sdb_get_stats_struct( context->id, (void**)&stats ); stats->mafi.data = 0; swr_sdb_free_stats_struct( context->id, (void**)&stats ); if ( sizeof( private_t ) > 0 ) swr_free( private ); MOD_DEC_USE_COUNT; return 0;}/* * This function is called upon "insmod" and is used to register the * different parts of the module to the SPM. */swr_spc_id_t rcv_id;int rcv_module_init(void) { swr_spc_desc_t *desc; char str[256]; int i; /** * Get a description-part from SPM * Give the following parameters: * Input-ports, output-ports, config-params, stat-params */ desc = swr_spc_get_new_desc( 1, 1, 5, ( 14 + MAX_CH_EST ) ); if ( !desc ) { PR_DBG( 0, "Can't initialise the module. This is BAD!\n" ); return -1; } /** * Define the different parts of config and stats. You have to define * them in the same order as they appear in the structures. The names * can be freely chosen. * * UM_CONFIG_{INT,DOUBLE,STRING128}( "name" ); * UM_STATS_{INT,DOUBLE,STRING128}( "name" ); */ UM_CONFIG_INT( "type", PARAMETER_DEBUG ); UM_CONFIG_INT( "index" ); UM_CONFIG_INT( "peak_location", PARAMETER_DEBUG ); UM_CONFIG_INT( "gain_control" ); UM_CONFIG_INT( "num_ch_est", PARAMETER_DEBUG ); UM_STATS_DOUBLE( "snr_mid" ); UM_STATS_DOUBLE( "snr_data" ); UM_STATS_INT( "peak_amp", PARAMETER_DEBUG ); UM_STATS_INT( "offset" ); UM_STATS_INT( "mid_amp" ); UM_STATS_INT( "mid_amp_old", PARAMETER_DEBUG ); UM_STATS_INT( "noise_var" ); UM_STATS_INT( "noise_var_old", PARAMETER_DEBUG ); UM_STATS_DOUBLE( "flip_prob" ); UM_STATS_DOUBLE( "snr_old", PARAMETER_DEBUG ); UM_STATS_BLOCK( "mafi" ); UM_STATS_BLOCK( "midamble" ); UM_STATS_COMPLEX( "peak", PARAMETER_DEBUG ); for ( i = 0; i<MAX_CH_EST ; i++ ) { sprintf( str, "peak_amp_stat%02i", i ); UM_STATS_INT( str, PARAMETER_DEBUG ); } UM_STATS_DOUBLE( "snr", PARAMETER_DEBUG ); /** * The in- and outputs have also to be defined in the right order. First * port first. The additional flag is not used yet, but it will... * * UM_INPUT( SIG_{U8,SYMBOL_{S16,COMPLEX,MMX},SAMPLE_S12,S32}, 0 ); * UM_OUTPUT( SIG_{U8,SYMBOL_{S16,COMPLEX,MMX},SAMPLE_S12,S32}, 0 ); */ UM_INPUT( SIG_SAMPLE_S12, 0 ); UM_OUTPUT( SIG_SYMBOL_COMPLEX, 0 ); // Initialise the callback-functions. Delete the ones you don't use desc->fn_init = rcv_init; desc->fn_reconfigure = rcv_reconfig; desc->fn_process_data = rcv_pdata; desc->fn_configure_inputs = rcv_configure_inputs; desc->fn_configure_outputs = rcv_configure_outputs; desc->fn_finalize = rcv_finalize; // And register the module in the SPM. rcv_id = swr_cdb_register_spc( &desc, "matched_filter" ); if ( rcv_id == SWR_SPM_INVALID_ID ) { swr_spc_free_desc( desc ); PR_DBG( 0, "Couldn't register the module!\n" ); return 1; } PR_DBG( 4, "Ready\n" ); return 0;}/* * This is called upon rmmod */void rcv_module_exit( void ) { PR_DBG( 4, "Freeing id: %i\n", rcv_id ); if ( swr_cdb_unregister_spc( rcv_id ) < 0 ) { PR_DBG( 0, "Still in use somewhere\n" ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -