📄 midamble_rcv.c
字号:
/*************************************************************************** * rcv.c - Software Radio matched filter * ------------------- * begin : 02/24/10 * authors : Linus Gasser * emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** * Changes * ------- * date - name - description * 02/24/10 - ineiti - begin * 03/01/23 - ineiti - add cut-parameter * 03/02/26 - ineiti - changed output from 32-bit to 16-bit * 03/03/13 - ineiti - no cut anymore * 03/04/24 - ineiti - better SNR calculation * mafi_e -> mid_amp * 03/04/25 - ineiti - changed peak_e to peak_amp * 03/07/25 - Selvan - made peak_amp as an array for different midamble index * 04/01/07 - ineiti - add snr_data and snr_mid (copy of "snr") * 04/03/06 - ineiti - adjusted description * 04/04/06 - ineiti - some debugging messages **************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************//** * The receiving part of the midamble - the matched filter. */#include <math.h>#include "spc.h"#include "midamble.h"#include "filtering.h"#include "antenna.h"#include "std.h"#define DBG_LVL 0#define ESTIMATION_LENGTH 64typedef struct { // Type of the midamble. The following indexes are available: // 1 - 3GPP type 1 (192+64 = 256) // 2 - User Def (512+32 = 544) // 3 - Midamble defined in Chinese WCDMA 128+16 = 144 int type; // 3 // The index of the received user. If more than one user sent in the // same timeslot, and each has a different index, each user can be // estimated by giving the corresponding index here. int index; // 0 // Where to put the peak_location. This is used because the channel // is non-causal. int peak_location; // 32 // If set to 1, gain-control will be done int gain_control; // 0 // Number of Channel estimates int num_ch_est; // 2}config_t;typedef struct { // Signal to noise ratio of the midamble double snr_mid; // Signal to noise ratio of the data-part double snr_data; // Peak-amplitude of the midamble int peak_amp; // How many samples we're off - the delay int offset; // The calculated midamble-amplitude int mid_amp; // An old and simple way to calculate the mid_amp int mid_amp_old; // The noise-variance int noise_var; // An old and inaccurate way to calculate the variance int noise_var_old; // The BER, or flip_probability double flip_prob; // mid_amp_old^2 / noise_var_old double snr_old; // A copy of the matched filter block_t mafi; // A copy of the midamble block_t midamble; // The highest tap SYMBOL_COMPLEX peak; // A midamble.^2 int peak_amp_stat[MAX_CH_EST]; // Copy of snr_mid, deprecated double snr;}stats_t;typedef struct { estimation_vars_t est; SYMBOL_COMPLEX mafi[ MAX_MIDAMBLE_PERIOD ]; SYMBOL_COMPLEX midamble[ MAX_MIDAMBLE_PERIOD ]; double rx_gain; int gain_control; int antenna; int peak_amp_stat[MAX_CH_EST];}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; int i; SYMBOL_COMPLEX n = {0,0}; 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 = 3; config->index = 0; config->peak_location = ESTIMATION_LENGTH / 2; config->gain_control = 0; config->num_ch_est = 2; private->est.estimation_length = ESTIMATION_LENGTH; private->rx_gain = 0.; private->antenna = 0; stats->offset = 0; stats->peak = n; // Put the matched filters available to the outside stats->mafi.data = private->mafi; stats->mafi.size = private->est.estimation_length; stats->mafi.type = SIG_SYMBOL_COMPLEX; // Show also the filtered midamble... stats->midamble.data = private->midamble; stats->midamble.size = MAX_MIDAMBLE_PERIOD; stats->midamble.type = SIG_SYMBOL_COMPLEX; for (i = 0; i < MAX_CH_EST; i++) { stats->peak_amp_stat[i] = 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}/* * 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) + midamble_get_length( config->type ) ) * DAQ_SAMPLES_PER_CHIP; // 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) / DAQ_SAMPLES_PER_CHIP - midamble_get_length( config->type ) ); // Definition - don't touch swr_sdb_free_config_struct( context->id, (void**)&config ); return 0;}/* * 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; swr_sdb_get_config_struct( context->id, (void**)&config ); // Change the midamble-type if ( ( config->type >= NUM_MIDAMBLE_DEF ) || ( config->type < 1 ) ) { PR_DBG( 0, "Midamble-type %i not available, only 1..%i are valuable types.\n", config->type, NUM_MIDAMBLE_DEF - 1 ); config->type = NUM_MIDAMBLE_DEF - 1; } // Change the midamble-index if ( config->index >= midamble_get_nbr_channels( config->type ) ) { PR_DBG( 0, "No midamble-index %i for midamble-type %i.\n", config->index, config->type ); config->index = midamble_get_nbr_channels( config->type ) - 1; } // Allow for reception-gain control if ( config->gain_control ) { if ( !private->gain_control ) { private->rx_gain = 0; //swr_ant_get_rx_gain( private->antenna ); } private->gain_control = config->gain_control; } else { private->gain_control = 0; } // Definition - don't touch swr_sdb_free_config_struct( context->id, (void**)&config ); return 0;}/* * 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 config_t *config; stats_t *stats; int type, index; int i,j, peak_amp, mid_amp_old, mid_amp; double flip_prob, noise_var, noise_var_old, tmp, data_amp; int mean_re, mean_im; estimation_vars_t *est = &private->est; midamble_t *m; SAMPLE_S12 *in; SYMBOL_COMPLEX *out, *mid_tx, *mid_rx, com_p; mmx_t *x; int mid_length, mid_start, rx_offset; int data_pos[2], data_len_half, slc; int stats_offset; int re,im,sq; //Used in peak_amp est // Initialise the configuration-variables swr_sdb_get_config_struct( context->id, (void**)&config ); type = config->type; index = config->index; rx_offset = -config->peak_location / 4; swr_sdb_free_config_struct( context->id, (void**)&config ); // Get input and reserve output-buffer in = buffer_in(0); out = buffer_out(0); PR_DBG( 4, "Buffer_in: %p, Buffer_out: %p\n", in, out ); // get some default variables m = &midamble_def[ type ]; mid_length = m->length; // The Slot Length in Chips slc = size_in(0) / DAQ_SAMPLES_PER_CHIP; x = (mmx_t*)in; x += rx_offset; mid_start = m->shift + ( slc - mid_length ) / 2; PR_DBG( 4, "Midamble-receive, %i, %i, %i, %i, %i\n", mid_start, slc, mid_length, rx_offset, m->shift ); m->estimate_channel( &x[mid_start], est->estimates, m->generatorF, m->twiddleFFT, m->twiddleIFFT, m->revbuf ); // build the matched filters // select the spreading sequence set // TODO: Do this for all indexes //collect all the channel info, selectively pick the channel estimate calculated. //Achieved by passing various values of channel types to the matched_filter_build function for(i = 0; i < 2 ; i++) { //replace 2 by config->num_ch_est - Selva matched_filter_build( m, est, i ); peak_amp = 0; sq = 0; for ( j = 0; j < private->est.estimation_length; j++) { re = est->matched_filter_Re[j]; im = est->matched_filter_Im[j]; sq = re * re + im * im; if ( sq > peak_amp ) { peak_amp = sq; } } private->peak_amp_stat[i] = sqrt( peak_amp ); //PR_DBG(0,"in the module peak_amp = %i\n",peak_amp); } // The requested channel-type estimation is performed matched_filter_build( m, est, index ); // Calculate the total peak_amp in the midamble and search for the // peak... for Nicolae. Don't take it out, yet, he will cry ;)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -