?? chest_rcv.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 * 04/03/06 - ineiti - adjusted description *//*************************************************************************** * * * 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. * * * ***************************************************************************//** * Using the midamble the channel is estimated for the given antenna. This module also removes * the midamble part of the data stream.*/#include "spc.h"#include "sequences.h"#include "std.h"#include <math.h>#define DBG_LVL 0typedef struct { //0-> MCCDMA, 1 -> Fra int type; // 0 //Necessary for noise variance estimation, represnts no. Tx antennas int num_of_antennas; // 1 // 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 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; int calc_taps; int align; int index;}private_t;/* * The initialisation function, or constructor, * is called the first time this module is instantiated. */int 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->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 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 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 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 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 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; int data_len[2]; 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; //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 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; 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; //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; } // Compute the matched filter: zero-forcing equalisation // channel_inv = ifft( 1./ fft( channel ) ) f_len = pow( 2, floor( logb( s_row ) ) ); f_abs = 0; for ( i=0; i<f_len; i++ ){ f_inv[i] = channel[i].real + channel[i].imag*I; }
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -