?? test_ldpc_mimo_general.c
字號:
/*************************************************************************** test_ldpc_mimo_general.c - a NxN MIMO 2-fold ldpc code ------------------- begin : 01 Sept 2003 authors : Nicolae Chiurtu emails : Nicolae.Chiurtu@epfl.ch ***************************************************************************//*************************************************************************** Changes ------- date - name - description 03/09/01 - Nicou - Begin 03/09/03 - ineiti - added complex channel 10 Dec 2003 - nicu & linus - make it general to work for up to 4 by 4 04/03/03 - ineiti - added a small 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. * * * ***************************************************************************/#include <stdlib.h>#include <complex.h>#include <fpu_control.h>#include "spc.h"#include "std.h"#include "math.h"#define DBG_LVL 0char desc[] ="Description:\n""This is a general NxN MIMO LDPC-code simulation, where 1<=N<=4.\n""It shows the result for increasing sigma. The BER for sigmas < 0.7\n""should be 0. Above that, the BER should rise to 0.2 or so.\n""The channel-matrix H is 'a_mn + b_mn * i', where a_mn and b_mn\n""are gaussian variables with variance 1 and mean 0.\n\n";// The number of experiments and variances#define NO_VAR 12#define NO_EXP 1#define NO_TX 2#define NO_RX 2#define BLOCK_LENGTH 4000double getSigma(double);complex double getSigmaComplex(complex double);struct chain_t *test_chain[ NO_TX + NO_RX ];void *start_it( void *arg ) { swr_sdb_id mid[NO_TX],src,block_complex; swr_sdb_id split, tsd, rcd, mid_rx[NO_RX],encoder,decoder; double total_errors; int a, b, c, d, e; int errors, total_info_bits; int MAX_NO_RX; double ber = 0.0; double real_sigma; double sigma_array[NO_VAR] = {3200., 6400., 9600., 12800., 16000., 19200., 22400., 25600., 28800., 32000., 35200., 38400.}; complex double h[NO_RX][NO_TX]; // Division by zero and overflow /* { *//* fpu_control_t fpu_err = 0x37f - _FPU_MASK_ZM - _FPU_MASK_OM; *//* _FPU_SETCW( fpu_err ); *//* } */ PR( "Setting up main-chain\n" ); // This chain simulates a simple 2x2 MIMO with two-folded LDPC test_chain[0] = swr_chain_create(NEW_SPC_VAR( "random", src ), NEW_SPC_VAR( "test_data_send", tsd), NEW_SPC_VAR( "ldpc_encode_2fold", encoder), NEW_SPC( "mapper"), NEW_SPC_VAR( "split", split ), NEW_SPC_VAR( "chest_send", mid[ 0 ] ), NEW_SPC_VAR( "block_4by4_complex", block_complex), NEW_SPC_VAR( "chest_rcv", mid_rx[ 0 ] ), NEW_SPC_VAR( "ldpc_decode_2fold_general", decoder), NEW_SPC_VAR( "test_data_rcv", rcd ), CHAIN_END ); MAX_NO_RX = swr_sdb_get_stats_int( block_complex, "max_no_rx" ); swr_sdb_set_config_int( block_complex, "size", BLOCK_LENGTH / 2 / NO_TX + 256 ); PR( "Setting up secondary chains\n" ); // Doing transmission chains 1..NO_TX for ( a=1; a<NO_TX; a++ ){ test_chain[ a ] = swr_chain_create( OLD_SPC_OUT( split, a ), NEW_SPC_VAR( "chest_send", mid[ a ] ), OLD_SPC_IN( block_complex, a ), CHAIN_END ); } // Doing reception chains 1..NO_RX for ( a=1; a<NO_RX; a++ ){ test_chain[ NO_TX + a - 1 ] = swr_chain_create( OLD_SPC_OUT( block_complex, a ), NEW_SPC_VAR( "chest_rcv", mid_rx[ a ] ), OLD_SPC_IN( decoder, a ), CHAIN_END ); } PR( "Chains are set up\n" ); // Precision of the DAD module swr_sdb_set_config_int( block_complex, "precision", 14 ); // setting the number of antennas for the block_complex for ( a=0; a<NO_RX; a++ ){ swr_sdb_set_config_int( mid_rx[a], "num_of_antennas", NO_RX ); swr_sdb_set_config_int_array( decoder, "chest", a, mid_rx[a] ); swr_sdb_set_config_int( mid_rx[a], "circ_ext", 0 ); } for ( a=0; a<NO_TX; a++ ){ swr_sdb_set_config_int( mid[a], "index", a ); swr_sdb_set_config_int( mid[a], "circ_ext", 0 ); } swr_sdb_set_config_int( rcd, "mode", 1 ); swr_sdb_set_config_int( encoder, "ldpc_code_id", 1 ); swr_sdb_set_config_int( decoder, "ldpc_code_id", 1 ); swr_sdb_set_config_int( decoder, "iterations", 15 ); swr_sdb_set_config_int( decoder, "iterations_left", 1 ); swr_sdb_set_config_int( decoder, "iterations_right", 1 ); swr_sdb_set_config_int( decoder, "no_tx", NO_TX ); swr_sdb_set_config_int( decoder, "no_rx", NO_RX ); swr_sdb_set_config_int( encoder, "bplcn", NO_TX * 2 ); PR( "Connecting the test_data modules\n" ); swr_conn_add(tsd, 1,rcd, 1); //swr_sdb_set_config_int( snk, "flag", 1 ); //dump PR( "Sending first message\n" ); for (a = 0; a < NO_VAR; a++ ) { // setting the noise variance for (c = 0; c < NO_RX; c++ ) { swr_sdb_set_config_complex_array( block_complex, "sigma", c, sigma_array[a] * ( 1.0 + 1.0*I ) ); } total_errors = 0.0; for (b = 0; b < NO_EXP; b++){ // setting the channel for(d = 0; d < NO_RX; d++){ for(e = 0; e < NO_TX; e++){ h[d][e] = getSigmaComplex(1.0 + 1.0*I); swr_sdb_set_config_complex_array( block_complex, "h", d * MAX_NO_RX + e, h[d][e] ); } } // print the channel and the variance to compare with the one which we estimate later // works for a = 0.01 for ( d=0; d<NO_RX; d++ ){ for ( e=0; e<NO_TX; e++ ){ PR_DBG_CL( 4, "tr-h%i%i(%g:%gi) ", d, e, floor(creal(h[d][e])*327.67), floor(cimag(h[d][e])*327.67 )); } } PR_DBG_CL( 4, "tr-var1(%g) tr-var2(%g) \n" , (double) pow(sigma_array[a]*0.01,2), (double) pow(sigma_array[a]*0.01,2) ); swr_sdb_send_msg( src, SUBS_MSG_USER, NULL, -1 ); //PR( "Total data: %i, Errors: %i\n", // swr_sdb_get_stats_int( rcd, "total" ), // swr_sdb_get_stats_int( rcd, "error" ) ); total_info_bits = swr_sdb_get_stats_int( rcd, "total" ); errors = swr_sdb_get_stats_int( rcd, "error" ); total_errors += errors;/* PR("Noise Variance ant 1 = [%i], ant 2 = [%i] \n", *//* swr_sdb_get_stats_int( mid_rx[0], "noise_var_real"), *//* swr_sdb_get_stats_int( mid_rx[1], "noise_var_real")); */ } // for number experiments ber = (double) total_errors / (NO_EXP * total_info_bits); real_sigma = (double) sigma_array[ a ] / 32767; // PR("Info bits = %i, errors = %i\n", total_info_bits, errors); PR("Sigma = %g, BER = %g\n", real_sigma, ber); } // for the number of variances return 0;}swr_spc_id_t spm_id;struct thread start;/** * This function is called upon "insmod" and is used to register the * different parts of the module to the SPM. */int um_module_init(void) { int i; PR_CL( desc ); for ( i=0; i<NO_TX+NO_RX; i++ ){ test_chain[i] = NULL; } if ( swr_thread_init( &start, start_it, NULL ) < 0 ) goto first_no_stack; return 0;first_no_stack: PR_DBG( 0, "Couldn't allocate stack\n" ); return -1;}void um_module_exit( void ) { int i; swr_thread_free( &start, NULL ); for ( i=NO_TX+NO_RX-1; i>=0; i-- ){ swr_chain_destroy( test_chain[ i ] ); } PR( "Finished and cleaned up\n" );}double getSigma( double amplitude ) { unsigned short x[3]; double u, v, w, alpha; x[0] = (unsigned short)((get_time_usec()>>00)&0xffff); x[1] = (unsigned short)((get_time_usec()>>16)&0xffff); x[2] = (unsigned short)((get_time_usec()>>00)&0xffff); do { u = 2*erand48(x)-1; v = 2*erand48(x)-1; w = u*u + v*v; } while (w>=1); alpha = sqrt( -2 * log(w)/w); return alpha * u * amplitude;}complex double getSigmaComplex( complex double amplitude ){ return getSigma( creal( amplitude ) ) + getSigma( cimag( amplitude ) ) * I;}module_init( um_module_init );module_exit( um_module_exit );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -