⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channel.c

📁 wcdma模型
💻 C
📖 第 1 页 / 共 2 页
字号:
/* | Project:     WCDMA simulation environment | Module:     | Author:      Maarit Melvasalo | Date:        February 1999 | | History: |              March 18,  1999 Maarit Melvasalo  |                      Channel memory vector changed to mode were  |                      several different vectors can be memorized   |       |              May 3, 1999 Maarit Melvasalo                  |                      Channel model changed |              June 16, 1999 Maarit Melvasalo   |                      Documentation added and cleaning up the code | | Copyright disclaimer: |   This software was developed at the National Institute of Standards |   and Technology by employees of the Federal Government in the course |   of their official duties. Pursuant to title 17 Section 105 of the |   United States Code this software is not subject to copyright |   protection and is in the public domain. | |   We would appreciate acknowledgement if the software is used. |/* * Static data structures. */#include <stdlib.h> #include <math.h>#include <stdio.h>#include "config_wcdma.h"#include "channel.h"#ifndef TRUE#define TRUE 1#define FALSE 0#endif /* TRUE *//* Channel matrix to keep in memory the channel impulses   (both amplitudes and delays and their changes)    and previous chips etc /**/static channel_matrix  channel_data[MAX_CHANNELS];/* List that keeps record which channel instances are used /**/static enum instance_state channel_alloc_list[MAX_CHANNELS] ;/* General initialization flag /**/static int general_channel_init_flag = FALSE;/* Total number of occupied channels/**/static int channel_index = 0;/* -------------------------------------------------------------------- *//* * Function:    wcdma_channel_init * Desc.:       Channel initialization *              Allocates memory for the chips that effect the future call time inputs   *  * Return:      instance number or -1 if all instances are already occupied. * * Note:       *//* -------------------------------------------------------------------- */int wcdma_channel_init(		      double channel_impulse[],	/* IN: Channel impulse vector*/		      int  channel_delays[],/* IN: Delay taps */		      int  nTaps,           /* IN: channel impulse vector size */		      int  nImpulse,        /* IN: number of channel impulse vectors */		      double impulse_prob[],/* IN: Channel impulse vector probabilities*/		      int  steps,           /* IN: Total number of frames send during ssim/**/		      double esno,          /* IN: SNR/**/		      double power,         /* IN: Power/**/		      int  nCode            /* IN: Length of the spreading code/**/){  int i,j,instance,n_intervals,delay_diff;    /*     * If first call, initialize static data.     */    if (general_channel_init_flag == FALSE) {        for (i=0; i < MAX_CHANNELS; i++) {            channel_alloc_list[i] = FREE_INSTANCE;        } /* for */        general_channel_init_flag = TRUE;    } /* if general_init_flag */    /*     * Find first free instance number.     */    instance = -1;    for (i=0; i < MAX_CHANNELS; i++) {        if (channel_alloc_list[i] == FREE_INSTANCE) {            instance = i;            break;        } }    if (instance == -1) return(-1); /* no free instances */    if (nCode < 0) return(-1); /* Spreading code length incorrect/**/      /*        Store the channel data	Note if the channel is changed there might be some old data	left in the memory, but this do not effect the calculations.	/**/    channel_data[instance].n_taps = nTaps;    channel_data[instance].n_impulses = nImpulse;    channel_data[instance].cur_impulse = 0;    /*        Standard noise deviation is calculated for each chip.       See  Michel C. Jeruchim:               "Simulation of communication Systems", Plenum 1992	      page. 283       Power  =  noise power       nCode = code length         esno = Signal to noise ratio       The random number is scaled between -1 and 1 and multiplied by noise_std       calculated here.      /**/    channel_data[instance].noise_std =        sqrt(power / nCode / 2 / pow(10.0,(esno/10.0)) ) ; /**/                /* Select the channel mode       CONSTANT       RANDOM       INTERPOL       /**/       if( nImpulse == 1)      { channel_data[instance].mode = CONST;} /* CONSTANT channel model /**/          else if (steps == 0)          /* RANDOM channel model /**/      { channel_data[instance].mode = RANDOM;      /* 	 Calculate cumulative impulse vector probalitites 	 /**/      channel_data[instance].cumul_prob[0] = impulse_prob[0];      for (i = 1; i < nImpulse; i++){	channel_data[instance].cumul_prob[i] = 	  impulse_prob[i] +  channel_data[instance].cumul_prob[i-1];      }}        else {        /* INTERPOLATING channel model /**/      channel_data[instance].mode = INTERPOL;       /* 	 Define the number of iteration steps in between two channel impulses	 /**/      n_intervals = ceil (steps / (nImpulse - 1)) + min(1, steps % (nImpulse - 1));/**/      for(j = 0; j<nImpulse; j++){	channel_data[instance].max[j] = n_intervals;	channel_data[instance].use[j] = 0;}    }    /*      Update the channel data matrix for all channel taps      /**/    for(i = 0; i < nTaps; i++){      channel_data[instance].cur_channel[i] = channel_impulse[i];      channel_data[instance].cur_delays[i] = channel_delays[i];      if( channel_data[instance].mode == RANDOM){	/* RANDOM channel model  	   Save all the impulses and delays	   /**/	for(j = 0; j < nImpulse; j++){	  channel_data[instance].amplitudes[j][i] = channel_impulse[j * nTaps + i]; 	  channel_data[instance].delays[j][i] = channel_delays[ j * nTaps + i];	}}      else if( channel_data[instance].mode == INTERPOL){ 	/* INTERPOLATING channel model 	   Calculate the derivates of the amplitudes and the  	   number of timesteps between delay tap changes (and the direction of the change)	   /**/	for(j = 0; j< nImpulse-1; j++){	  channel_data[instance].amplitudes[j][i] = 	      (channel_impulse[(j+1) * nTaps + i] - channel_impulse[j * nTaps + i])/n_intervals;	  delay_diff = channel_delays[(j+1) * nTaps + i] - channel_delays[j * nTaps + i] ;	  if( delay_diff != 0) {	    channel_data[instance].delays[j][i] =  	      ( n_intervals / (abs(delay_diff)+1) + min(1, n_intervals % (abs(delay_diff)+1))) ;            if( delay_diff < 0 )  {	      channel_data[instance].delays[j][i] = -  channel_data[instance].delays[j][i] ;}	  }	  else {channel_data[instance].delays[j][i] = 0;}	}}    } /*Update for each channel tap/**/        /*        Find the longest delay in the channel (to allocate enough memory for stored chips)       /**/    channel_data[instance].max_memory = channel_delays[nTaps-1];    for (j = 2; j <= nImpulse; j++){      if ( channel_delays[j * nTaps - 1]  > channel_data[instance].max_memory )	    channel_data[instance].max_memory = channel_delays[j * nTaps-1];     }    /*      Allocate memory for the memory storage of previous time chips      /**/    channel_data[instance].I_prev_chips  = (int*)calloc( channel_data[instance].max_memory, sizeof(int));    channel_data[instance].Q_prev_chips  = (int*)calloc( channel_data[instance].max_memory, sizeof(int));    /*        Update the static tables to keep in mind which channel instances are in use       /**/        channel_alloc_list[instance] = INSTANCE_IN_USE;    channel_index ++;    /*      If you want to check what has been updated call:      channel_print(instance);/**/    return(instance);}/* -------------------------------------------------------------------- *//* * Function:    wcdma_channel * Desc.:       Channel response *              The function which performs the givne channel *              for the input signal and upstaes the channel *              and stores the last chips for next call.   * * Note: *         channel_impulse and tap_delay vectors need to same length and *         their elements are corresponding, i.e. the tap_delay[i]  *         indicates how many chipintervals the channel_impulse  *         is delayd. The channel_impulse[i] indicates the attennuation *         coefficient.  * *        THE LAST ELEMENT OF tap_delay[i] VECTOR IMPLIES WHAT IS THE TOTAL *        DELAY FOR THE CHANNEL.  *//* -------------------------------------------------------------------- */int wcdma_channel( 	     int  Inputs[],	        /* IN: input chip vector */	     int  Qnputs[],	        /* IN: input chip vector */	     int  nInputs,	        /* IN: input vector size */	     int  instance,	        /* IN:  */	     double channel[],          /* OUT: Channel impulse vector*/	     int  delay[],              /* OUT: Delays of channel taps*/	     double Iout[],             /* OUT: output bit vector */ 	     double Qout[]              /* OUT: output bit vector */){    int i,  memory_length, nTaps ;    double std_noise;    int *prev_I,*prev_Q;    channel_matrix *channel_datum;    /*      Get the channel data for given channel instance      /**/    channel_datum = &channel_data[instance];    nTaps = channel_datum->n_taps;    std_noise = channel_datum->noise_std ;    /*        If AWGN noise is added to the channel       /**/    if(std_noise > 0 )      i = wcdma_channel_conv(Inputs,Qnputs,nInputs,instance,Iout,Qout);    /*        If no noise is added /**/ 	    else      i = wcdma_channel_conv_nonoise(Inputs,Qnputs,nInputs,instance,Iout,Qout);        /*        Return the used channel amplitude and delay vectors       /**/    for(i=0;i<nTaps;i++){      channel[i] = channel_datum->cur_channel[i];      delay[i] = channel_datum->cur_delays[i];    }    /*        Update the channel amplitude and delay vectors if not CONSTANT channel       /**/        if (channel_datum->mode > CONST){      wcdma_update_channel(channel_datum);    }    /*        Save the last chips of this input block to next function call       /**/    i = wcdma_update_memory_chips(Inputs,Qnputs,nInputs,channel_datum);    /**/        return(0);}/* -------------------------------------------------------------------- *//* * Function:    wcdma_channel_conv_nonoise  * Desc.:       Channel response *              Performs the channel concolution and adds no noise to it *              (i.e. is almost the same as function wcdma_channel_conv) * Note: *         channel_impulse and tap_delay vectors need to same length and *         their elements are corresponding, i.e. the tap_delay[i]  *         indicates how many chipintervals the channel_impulse  *         is delayd. The channel_impulse[i] indicates the attennuation *         coefficient.  * *        THE LAST ELEMENT OF tap_delay[i] VECTOR IMPLIES WHAT IS THE TOTAL *        DELAY FOR THE CHANNEL.  *//* -------------------------------------------------------------------- */int wcdma_channel_conv_nonoise( 	     int  Inputs[],	        /* IN: input chip vector */	     int  Qnputs[],	        /* IN: input chip vector */	     int  nInputs,	        /* IN: input vector size */	     int  instance,	        /* IN: indicates the channel instance used/**/ 	     double Iout[],             /* OUT: output bit vector */	     double Qout[]              /* OUT: output bit vector */){    int i, j, i_tmp, tmp_delay,d_zero;    int  taps, mem_len;    double I_collect , Q_collect , noise,std_noise;    int  *delay, *prev_I, *prev_Q;    double  *channel;    channel_matrix *channel_datum;    /*      Get infromation about the used channel from the channel matrix      /**/          channel_datum = &channel_data[instance];    taps = channel_datum->n_taps;    /*        Current channel amplitudes and delays       /**/    channel = &channel_datum->cur_channel[0];    delay = &channel_datum->cur_delays[0];    mem_len = delay[taps -1];    /*      The chips saved from previous function call      /**/    prev_I = &(channel_datum->I_prev_chips[0]);    prev_Q = &(channel_datum->Q_prev_chips[0]);    /*        The first mem_len chips are effected also by the        previous input chips.        /**/    for(i = mem_len ; i > 0; i--) {      I_collect = 0;  /* gathers all the multipaths signals for I /**/      Q_collect = 0;  /* and for Q/**/      d_zero = i - mem_len;      for(j = 0; j < taps; j++) {	    i_tmp = d_zero + delay[j];             if( i_tmp > 0) {	      /* Use the stored chips to update the output		 /**/	      I_collect += prev_I[i_tmp - 1] * channel[j];	      Q_collect += prev_Q[i_tmp - 1] * channel[j];	    } 	    else {	      /* Use the new input chips  to update the output		 /**/	      i_tmp = abs(i_tmp);	      I_collect += Inputs[i_tmp] * channel[j];	      Q_collect += Qnputs[i_tmp] * channel[j];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -