📄 channel.c
字号:
/* | 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 + -