📄 fading_multi_complex.c
字号:
/*************************************************************************** fading_multi.c - Module for a complex multi-path fading noise channel ------------------- begin : 2003 authors : Philippe Roud emails : philippe.roud@epfl.ch ***************************************************************************//*************************************************************************** Changes ------- date - name - description 03-11-15 - phil - begin 04/03/01 - ineiti - added auto-receive for transmitting antennas, that is, a tx-slot is copied to the rx-part (kind of simulates better the hardware 04/03/19 - ineiti - fixed partial rx- or tx- blocks 04/05/14 - ineiti - respect the value of TX_OFF in a more general way **************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************/#include <math.h>#include <stdlib.h>#include <complex.h>#include "system.h"#include "debugging.h"#include "server.h"#define DBG_LVL 0#define FADING_CHANNEL 0/** * @short a simple fading channel with no reflexions for complex numbers */double path_loss_fading_multi[MAX_CLIENTS][MAX_CLIENTS], noise;double u,v,r,s;double alpha, w,p;unsigned short simrand[3];// The variance of the Gaussian noiseint null_out;// Set the variance of the Gaussian noise// If it is too low, it could hinder some modules to function// properly...double sigma_real = 50.;/** * @short initialises the channel */void fading_multi_complex_init() { int t, i, j; struct timeval tp; // Set the white noise to 0 noise = 0; // initialize the random generator gettimeofday(&tp,NULL); simrand[0]=(unsigned short)(tp.tv_sec&0177777); simrand[1]=(unsigned short)((tp.tv_sec>>12)&0177777); simrand[2]=(unsigned short)((tp.tv_sec>>24)&0177777); // Creates default unitary channels and one 0-channel for ( i=0; i< MAX_CLIENTS; i++ ) { PR_DBG( 4, "Receiver %i\n", i ); for( j = 0; j < MAX_CLIENTS; j++){ PR_DBG( 4, " Sender %i: ", j ); for ( t=0; t<CHANNEL_LENGTH; t++ ) { //Channel set for BS->MS channel_tap_cplx[ i ][ j ][ t ] = (t == 0) * (i<MAX_CLIENTS); PR_DBG_CL( 4, "%i+I*%i ", (int)creal(channel_tap_cplx[ i ][ j ][ t ]) > 0., (int)cimag(channel_tap_cplx[ i ][ j ][ t ]) > 0. ); } PR_DBG_CL( 4, "\n" ); } }}double getSigma( double amp ){ double u, v, w; do { u = 2*erand48(simrand)-1; v = 2*erand48(simrand)-1; w = u*u + v*v; } while (w>=1); alpha = sqrt( -2 * log(w)/w); return alpha * u * amp;}#define sign(x) ((x)>=0?1:-1)#define TX_OFF_16 ( 0x101 * TX_OFF )/** * @short calculates the fading */void fading_multi_complex_calc( int nb_clients, int gid ) { int n,i,j, t; short *rx, *tx; double complex res, tx_cplx; double complex taps[ CHANNEL_LENGTH ]; double gain; PR_DBG( 4, "calculating block %i\n", tx_block ); for ( i = 0; i < MAX_CLIENTS; i++ ) { if ( client[i].id == -1 ) { continue; } // For all receiving clients // Initialise the rx-block. Three cases may occur: // - whole block in rx-mode: set to zero // - some in rx-mode, some in tx-mode: zero rx-part and copy tx-part // - whole block in tx-mode: copy to the rx-block // We assume that the mode only changes once a block. So it is enough // to look at the start (tx[0]) and at the end (tx[DAQ_DMA_BLOCK_SIZE_SAMPLES-1]) // to know where we're at rx = (short*)rx_signal_buffer[i][BLOCK_ACT_RX(tx_block)]; tx = (short*)tx_signal_buffer[i][BLOCK_ACT_TX(tx_block)]; if ( tx[0] == TX_OFF_16 && tx[DAQ_DMA_BLOCK_SIZE_SAMPLES-1] == TX_OFF_16 ){ // We're in reception mode, so start with an empty block memset( rx, 0, DAQ_DMA_BLOCK_SIZE_BYTES ); } else if ( tx[0] == TX_OFF_16 || tx[DAQ_DMA_BLOCK_SIZE_SAMPLES-1] == TX_OFF_16 ){ // The switching point is somewhere in this block, so put all // reception-samples to 0 and copy the transmission-samples to itself for ( n=0; n<DAQ_DMA_BLOCK_SIZE_SAMPLES; n++ ){ if ( tx[n] == TX_OFF_16 ){ rx[n] = 0; } else { rx[n] = tx[n]; } } } else { // Loop back the sent signal to itself if in transmission mode for // the whole block memcpy( rx, tx, DAQ_DMA_BLOCK_SIZE_BYTES ); } for (j=0;j<MAX_CLIENTS;j++) { int rcv = 1; // There is no such client if ( client[j].id == -1 ){ continue; } // Sending to itself is already taken care of if ( j == i ){ continue; } // We don't send a signal between antennas from same // group if ( client[j].gid == client[i].gid ) { continue; } tx = (short*)tx_signal_buffer[j][BLOCK_ACT_TX(tx_block)]; // If the sender is TX_OFF_16 throughout, this means that there is nothing // to send, but rather in receiving mode. So we don't do any // calculations on this... for ( n=0; n<DAQ_DMA_BLOCK_SIZE_SAMPLES; n++ ) { if ( tx[n] != TX_OFF_16 ){ rcv = 0; break; } } if ( rcv ){#if FADING_CHANNEL // This implements a slowly-fading (constant channel over one slot) // channel complex double ct; // The sender is listening, so let's change the channel ct = getSigma( 1 ) + getSigma( 1 ) * I; channel_tap_cplx[ i ][ j ][ 0 ] = ct; if ( j >= 2 ){ ct *= 600; PR_DBG( 4, "h[%i][%i] = %g + %gi\n", i, j, creal( ct ), cimag( ct ) ); }#endif continue; } // The gain between the sender and receiver gain = 300. / ( 1 << 14 ) * rx_gain[i] * tx_gain[j]; // Some debug-information if ( !( tx_block % 1000 ) ) { PR_DBG( 4, "tx_gain[%i] = %e, rx_gain[%i] = %e\n", j, tx_gain[j], i, rx_gain[i] ); PR_DBG( 4, "From %i to %i, gain %e\n", j, i, gain ); PR_DBG( 4, "Taps: " ); } // Calculation of the channel taps for ( t=0; t<CHANNEL_LENGTH; t++ ) { taps[ t ] = channel_tap_cplx[ i ][ j ][ t ] * gain; if ( i == 0 && j == 2 ){ PR_DBG( 4, "gain: %g, taps is %g + %gI\n", gain, creal( taps[ t ] / gain ), cimag( taps[ t ] / gain ) ); } if ( !( tx_block % 1000 ) ) { PR_DBG_CL( 4, "%i+I*%i ", creal(taps[ t ]) > 0.,cimag(taps[ t ]) > 0. ); } } if ( !( tx_block % 1000 ) ) { PR_DBG_CL( 4, "\n" ); } for ( n = 0; n < DAQ_DMA_BLOCK_SIZE_SAMPLES; n+=2 ) {#if 0 rx[n] += tx[n] / 16; rx[n+1] += tx[n+1] / 16;#else // Convolution of emitted signal with the channel for ( t=0, res=0; t<CHANNEL_LENGTH; t++ ) { tx_cplx = tx[n-2*t] + I*tx[n+1-2*t]; res += tx_cplx * taps[t]; } rx[n] += creal( res ); rx[n+1] += cimag( res );#endif } } // For all samples, add some noise. If we'd do it in the // loop, we'd add noise for every incoming channel, which // would be wrong. for ( n = 0; n < DAQ_DMA_BLOCK_SIZE_SAMPLES; n++ ) { // Add noise rx[n] += getSigma( sigma_real ); rx[n] &= 0xfff0; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -