?? chest_rcv_mimo_ics.c
字號:
/*************************************************************************** * chest_rcv.c - MIMO channel estimation module * begin : 03/08/05 * Author : Selvavinayagam Gunabalan * emails : selvan@kth.se ***************************************************************************//*************************************************************************** * * Changes * ------- 03/08/05 - Selvan - Begin 03/08/14 - Selvan - Added variance of noise estimation 04/01/12 - ineiti - added a matched filter as option January - February 2004 - some other changes from Linus in order to make it work with the SISO_LPDC March 2004 - nicou: modify to search for the highest tap and pass it to the ldpc. *//*************************************************************************** * * * 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 * * (at your option) any later version. * * * ***************************************************************************//** * Mimo Channel Estimation is done in the module * Also the Midambles are removed */#include "spc.h"#include "sequences.h"#include "std.h"#include <math.h>#define DBG_LVL 0typedef struct { //0-> MCCDMA, 1 -> Fra int type; //Necessary for noise variance estimation, represnts no. Tx antennas int num_of_antennas; // How many taps shall be used in the channel equalisation. If you // want to use the signal for some decoding, this is best left to // 0 (which means the signal won't be altered and you only get a channel // estimation). If there is some hard-decision, put it to 1 or more int calc_taps; // 0 // 0-> don't move the signal // else align output to the strongest tap of channel "align" // if calc_taps > 0, then align means that the number of taps calculated // are 'around' the peak of the channel impulse response. int align; // 0 // The midamble-index for this chest int index; // 0 // The length of the circular extension int circ_ext; // 8}config_t;typedef struct { // The channel of all N received antennas block_t channel; // The inversed channel block_t channel_inv; // The midamble block_t midamble; // The peaks corresponding to the NO_RX channels block_t transfer_matrix; // The SNR in db double snr; // The general noise variance = Realpart+Imagpart int noise_var; //Real part int noise_var_real; //Imag part int noise_var_imag; // The length of the channel impulse response int ch_length; // The peak of the midamble int peak_pos; // peak-amplitude of the midamble int peak_amp; // mean midamble-amplitude int mid_amp;}stats_t;typedef struct { SYMBOL_COMPLEX channel[ MAX_NO_OF_ANT * MAX_NO_OF_TAPS ]; SYMBOL_COMPLEX channel_inv[ MAX_NO_OF_ANT * MAX_NO_OF_TAPS ]; SYMBOL_COMPLEX *mid; SYMBOL_COMPLEX transfer_matrix[ MAX_NO_OF_ANT ]; int calc_taps; int align; int index;}private_t;/* * The initialisation function, or constructor, * is called the first time this module is instantiated. */int ics_rcv_init( swr_sdb_t *context ) { // Begin system-definitions { config_t *config; stats_t *stats; MOD_INC_USE_COUNT; if ( sizeof( private_t ) > 0 ) context->private_data = swr_malloc( sizeof( private_t ) ); swr_sdb_get_config_struct( context->id, (void**)&config ); swr_sdb_get_stats_struct( context->id, (void**)&stats ); // } End of system-definitions config->type = 0; config->num_of_antennas = 1; //SISO case! config->calc_taps = 0; config->align = 0; config->index = 0; config->circ_ext = 8; private->mid = NULL; stats->transfer_matrix.data = private->transfer_matrix; stats->transfer_matrix.size = MAX_NO_OF_ANT; stats->transfer_matrix.type = SIG_SYMBOL_COMPLEX; stats->channel.data = private->channel; stats->channel.size = MAX_NO_OF_ANT * MAX_NO_OF_TAPS; stats->channel.type = SIG_SYMBOL_COMPLEX; stats->channel_inv.data = private->channel_inv; stats->channel_inv.size = MAX_NO_OF_ANT * MAX_NO_OF_TAPS; stats->channel_inv.type = SIG_SYMBOL_COMPLEX; stats->midamble.size = 0; stats->midamble.type = SIG_SYMBOL_COMPLEX; stats->ch_length = 0; stats->snr = 1.0; stats->noise_var = 0; stats->noise_var_real = 0; stats->noise_var_imag = 0; stats->peak_pos = 0; stats->mid_amp = 0; stats->peak_amp = 0; // Begin system-definitions swr_sdb_free_stats_struct( context->id, (void**)&stats ); swr_sdb_free_config_struct( context->id, (void**)&config ); return 0; // End system-definitions}/* * Every time modules from the outside change the value of a configuration parameter, * this function is called. */int ics_rcv_reconfig( swr_sdb_t *context ) { // Definition of variables - don't touch config_t *config; stats_t *stats; swr_sdb_get_config_struct( context->id, (void**)&config ); swr_sdb_get_stats_struct( context->id, (void**)&stats ); if ( ( config->type >= TRAINING_SEQUENCES ) || ( config->type < 0 ) ) { PR_DBG( 0, "Midamble-type %i not available, " "only 0..%i are valuable types.\n", config->type, TRAINING_SEQUENCES - 1 ); config->type = TRAINING_SEQUENCES - 1; } private->calc_taps = min( config->calc_taps, MAX_NO_OF_ANT * MAX_NO_OF_TAPS ); private->align = config->align; private->index = config->index; if ( private->mid ){ swr_free( private->mid ); private->mid = 0; } stats->midamble.size = training_seq[ config->type ].Nt; private->mid = swr_malloc( sizeof( SYMBOL_COMPLEX ) * stats->midamble.size ); stats->midamble.data = private->mid; // Definition - don't touch swr_sdb_free_stats_struct( context->id, (void**)&stats ); swr_sdb_free_config_struct( context->id, (void**)&config ); return 0;}/* * To configure the inputs * this is called when the output-sizes change. */int ics_rcv_configure_inputs( swr_sdb_t *context ) { // Definition of variables - don't touch config_t *config; swr_sdb_get_config_struct( context->id, (void**)&config ); size_in(0) = size_out(0) + training_seq [ config->type ].Nt + config->circ_ext; // Definition - don't touch swr_sdb_free_config_struct( context->id, (void**)&config ); return 0;}/* * To configure the outputs * this is called when the input-sizes change */int ics_rcv_configure_outputs( swr_sdb_t *context ) { // Definition of variables - don't touch config_t *config; swr_sdb_get_config_struct( context->id, (void**)&config ); size_out(0) = size_in(0) - training_seq[ config->type ].Nt - config->circ_ext; // Definition - don't touch swr_sdb_free_config_struct( context->id, (void**)&config ); return 0;}/** * Calculate the convolution of the signal with the matched filter */void ics_do_mafi( SYMBOL_COMPLEX *in, SYMBOL_COMPLEX *out, complex double *f, double f_abs, int taps, int length ){ int i, j; for ( i=0; i<length; i++ ){ complex double o; o = SC_MULT_CD( in[i], f[0] ); for ( j=1; j<taps; j++ ){ o += SC_MULT_CD( in[i+j], f[-j] ); } out[i] = CD_TO_SC( o / f_abs ); }}/* * This is the function that implements the `main method' of the class * Every class has got just ONE method/working-mode. */int ics_rcv_pdata( swr_sdb_t *context ) { // Definition of variables - don't touch stats_t *stats; config_t *config; SYMBOL_COMPLEX *in,*out, *mid, *channel, *channel_inv, *transfer_matrix; int data_len[2], transfer_matrix_pos[4]; int type, num_of_antennas, peak_pos = 0, peak_amp, mid_amp, circ_ext; short s_column; // Number of columns of shsish (S Hermitian S )inverse S hermitian matrix short s_row; //Number of rows of shsish (S Hermitian S )inverse S hermitian matrix short i,j,mp_pos; //counter double *par; //Parity matrix = shsish short int *seq; short channel_offset; short seq_offset; short length; double double_real = 0.; double double_imag = 0.; double max_peak = 0; double tmp =0.; int noise_term_real = 0; int noise_term_imag = 0; int real_term = 0; int imag_term = 0; double var_noise_term_imag = 0, var_noise_term_real = 0; int noise_var = 0; int noise_var_real = 0; int noise_var_imag = 0; double sig_power = 0.; complex double f_inv[ 128 ]; int f_len, f_max = 0; double f_abs; int started = context->time_prepare; in = buffer_in(0); out = buffer_out(0); // These two might actually differ... data_len[0] = size_out(0) / 2; data_len[1] = size_out(0) - data_len[0]; swr_sdb_get_config_struct( context->id, (void**)&config ); type = config->type; num_of_antennas = config->num_of_antennas; circ_ext = config->circ_ext; swr_sdb_free_config_struct( context->id, (void**)&config ); //Points to the last Midamble rcvd mid = in + data_len[0] + training_seq[ type ].Nt - 1; channel = private->channel; channel_inv = private->channel_inv; transfer_matrix = private->transfer_matrix; //Matrix Multiplication of sshish_ * received midamble s_column = (training_seq[ type ].Nt - training_seq[ type ].L + 1 ); s_row = training_seq[ type ].M * training_seq[ type ].L; par = training_seq[ type ].shsish; seq = training_seq[ type ].sequence; for (i = 0; i < s_row; i++) { double_real = 0.; double_imag = 0.; for (j = 0; j < s_column; j++) { double_real += par[ 2*j + 2*i*s_column ] * mid[ -j ].real - par[ 2*j + 1 + 2*i*s_column ] * mid[ -j ].imag; double_imag += par[ 2*j + 2*i*s_column ] * mid[ -j ].imag + par[ 2*j + 1 + 2*i*s_column ] * mid[ -j ].real; } channel[ i ].real = double_real; //Quantization double -> int channel[ i ].imag = double_imag; } // get the peaks and construct the complex channel matrix // of size NO_RX // you get it row by row because one chest is estimating // one row of the channel transfer matrix for ( i=0; i < MAX_NO_OF_ANT; i++ ){ max_peak = 0; mp_pos = 0; for ( j=0; j<MAX_NO_OF_TAPS; j++ ){ if ( max_peak < cabs( SC_TO_CD( channel[j + i * MAX_NO_OF_TAPS] ) )){ max_peak = cabs( SC_TO_CD( channel[j + i * MAX_NO_OF_TAPS] ) );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -