📄 build_midamble.c
字号:
/* This file contains the definitions for the midamble. Alessandro Nordio 27/02/2001 History : Created 27/02/2001 01/03/01 The function Build_Mid_Table has been modified. Now only 1 argument is passed. 02/10/24 The file finds its way in the modularised version 03/05/23 We still have to fix it for gcc-3.2*/#include "midamble.h"#include "debugging.h"#include "estimation.h"#define DBG_LVL 4midamble_t midamble_def[ NUM_MIDAMBLE_DEF ];mmx_t mapping_def[ 2 ][ 4 ];// Get ith bit in unsigned int array#define GET_ith_BIT(in,i) ((in[i >> 5] >> (i & 0x1F))&1)// Pre-Defined Midambles:// 1 - 3GPP type 1 (192+64 = 256)#include "Gpp_Mid_Generators192.h"// include twiddles for a 768 points FFT (768=4*192) The format is specified// inside the included file#include "twiddle768.h"// include 1/FFT() of the 0-th midamble generator in mmx_t format// (see the included file for more informations)#include "Gpp_Mid_GeneratorF192.h"unsigned int Gpp_Mid_Table1[8*3]; // 8 = 256/32; 3 possible shiftsunsigned short Reverse_Buffer768[768]; // is a 768 elements FFT// 2 - User Def (512+32 = 544)#include "User_Def_Mid_Generators512.h"// include twiddles for a 2048 points FFT (2048=4*512) The format is specified// inside the included file#include "twiddle2048.h"// include 1/FFT() of the 0-th midamble generator in mmx_t format// (see the included file for more informations)#include "User_Def_Mid_GeneratorF512.h"// 17 = ceil((512+32)/32); 16 possible shiftsunsigned int User_Def_Mid_Table512[17*16];// is a 512 elements FFTunsigned short Reverse_Buffer2048[2048];// 3 - Midamble defined in Chinese WCDMA 128+16 = 144// include midamble table#include "User_Def_Mid_Generators128.h"// include twiddles for a 512 points FFT (512=4*128) The format is specified// inside the included file#include "twiddle512.h"// include 1/FFT() of the 0-th midamble generator in mmx_t format// (see the included file for more informations)#include "User_Def_Mid_GeneratorF128.h"// 5 = ceil((128+16)/32); 16 possible shiftsunsigned int User_Def_Mid_Table128[5*16];// is a 512 elements FFTunsigned short Reverse_Buffer512[512];unsigned short reverse_bits ( unsigned index, unsigned NumBits ) { unsigned i, rev; for ( i=rev=0; i < NumBits; i++ ) { rev = (rev << 1) | (index & 1); index >>= 1; } return rev;}int build_midamble_table( midamble_t *m );/** * Prepares the defined midambles, filling each structure with the data. * To define a new midamble declare it as global variable in L1_extern.h and L1_vars.c * and add its definition inside this function. */void midamble_prepare(void) { int i, j; // counter // mapping used for 3GPP midamble (when the first bit is real) mapping_def[0][0].w[0] = 1; mapping_def[0][0].w[1] = 0; mapping_def[0][0].w[2] = 0; mapping_def[0][0].w[3] = 1; mapping_def[0][1].w[0] = -1; mapping_def[0][1].w[1] = 0; mapping_def[0][1].w[2] = 0; mapping_def[0][1].w[3] = 1; mapping_def[0][2].w[0] = 1; mapping_def[0][2].w[1] = 0; mapping_def[0][2].w[2] = 0; mapping_def[0][2].w[3] = -1; mapping_def[0][3].w[0] = -1; mapping_def[0][3].w[1] = 0; mapping_def[0][3].w[2] = 0; mapping_def[0][3].w[3] = -1; // mapping used for 3GPP midamble (when the first bit is imaginary) mapping_def[1][0].w[0] = 0; mapping_def[1][0].w[1] = 1; mapping_def[1][0].w[2] = 1; mapping_def[1][0].w[3] = 0; mapping_def[1][1].w[0] = 0; mapping_def[1][1].w[1] = -1; mapping_def[1][1].w[2] = 1; mapping_def[1][1].w[3] = 0; mapping_def[1][2].w[0] = 0; mapping_def[1][2].w[1] = 1; mapping_def[1][2].w[2] = -1; mapping_def[1][2].w[3] = 0; mapping_def[1][3].w[0] = 0; mapping_def[1][3].w[1] = -1; mapping_def[1][3].w[2] = -1; mapping_def[1][3].w[3] = 0; // midamble_def[0] the type 0 midamble defined by 3GPP midamble_def[0].length = 512; midamble_def[0].period = 456; midamble_def[0].shift = 57; midamble_def[0].max_channels = 8; // the 1824 elements FFT is not implemented yet // midamble_def[1] the type 1 midamble defined by 3GPP midamble_def[1].length = 256; midamble_def[1].period = 192; midamble_def[1].shift = 64; midamble_def[1].max_channels = 3; // 6 is given by 192/32 we pointh to the 0-th generator // there are 128 generatores available midamble_def[1].generator = Gpp_Midamble_Generators1; // points to the pre-defined midamble table midamble_def[1].midamble_table = Gpp_Mid_Table1; build_midamble_table(&midamble_def[1]); // fill channel estimation fields midamble_def[1].generatorF = (mmx_t *)Gpp_Mid_GeneratorF192; midamble_def[1].twiddleFFT = (mmx_t *)twiddleFFT_768; midamble_def[1].twiddleIFFT = (mmx_t *)twiddleIFFT_768; midamble_def[1].revbuf = Reverse_Buffer768; for( i=0; i<256; i++ ) { j = reverse_bits( i, 8 ); midamble_def[1].revbuf[ 3*i ] = j; midamble_def[1].revbuf[ 3*i+1 ] = 256 + j; midamble_def[1].revbuf[ 3*i+2 ] = 512 + j; } midamble_def[1].estimate_channel = channel_estimation_768; // This is a user defined midamble // period +extension = 544 midamble_def[2].length = 512+32; midamble_def[2].period = 512; midamble_def[2].shift = 32; midamble_def[2].max_channels = 16; midamble_def[2].generator = User_Def_Midamble_Generators512; // points to the pre-defined midamble table midamble_def[2].midamble_table = User_Def_Mid_Table512; build_midamble_table(&midamble_def[2]); // fill channel estimation fields midamble_def[2].generatorF = (mmx_t *)User_Def_Mid_GeneratorF512; midamble_def[2].twiddleFFT = (mmx_t *)twiddleFFT_2048; midamble_def[2].twiddleIFFT = (mmx_t *)twiddleIFFT_2048; midamble_def[2].revbuf = Reverse_Buffer2048; // compute the reverse buffer for( i=0; i<2048; i++ ) { // 11 = log2(2048) midamble_def[2].revbuf[i] = reverse_bits( i, 11 ); } midamble_def[2].estimate_channel = channel_estimation_2048; // Midamble defined in Chinese WCDMA 128+16 = 144 // period + extension = 144 midamble_def[3].length = 128+16; midamble_def[3].period = 128; midamble_def[3].shift = 16; midamble_def[3].max_channels = 8; midamble_def[3].generator = User_Def_Midamble_Generators128; // points to the pre-defined midamble table midamble_def[3].midamble_table = User_Def_Mid_Table128; build_midamble_table(&midamble_def[3]); // fill channel estimation fields midamble_def[3].generatorF = (mmx_t *)User_Def_Mid_GeneratorF128; midamble_def[3].twiddleFFT = (mmx_t *)twiddleFFT_512; midamble_def[3].twiddleIFFT = (mmx_t *)twiddleIFFT_512; midamble_def[3].revbuf = Reverse_Buffer512; // compute the reverse buffer for( i=0; i<512; i++ ) { // 9 = log2(512) midamble_def[3].revbuf[i] = reverse_bits(i,9); } midamble_def[3].estimate_channel = channel_estimation_512;}/* * BuildMidTable is given an array "in" of int containing "insize" bits. * It produces a matrix where is * is the periodic extension of "in" to a size "outsize", * starting at 0, with successive shifts "shift". * The output bits are flipped according to TX_FLIPs[4] in order to get * j^k modulation */int build_midamble_table( midamble_t *m ) { // defines flips for j^k modulation // if shift is not an integer multiple of 4 then for // each user we should user different flips !!!! unsigned int tx_flips[4] = {0x66666666,0x33333333,0x99999999,0xCCCCCCCC}; // This is the flip used for a certain user midamble unsigned int flip; // Counts the sequences unsigned int j; // Counts the bits in the sequences unsigned int k; // Input bit index unsigned int t; unsigned int word; // retrieve some parameters from m unsigned int *in = m->generator; unsigned int *out = m->midamble_table; unsigned int insize = m->period; unsigned int shift = m->shift; unsigned int numseq = m->max_channels; unsigned int outsize = m->length; for (j = 0; j < numseq; j++) { // choose the FLIP pattern for this shift flip = tx_flips[(j*shift) & 0x00000003]; // Reset word for each sequence word = 0; t = (short unsigned int) j * (short unsigned int) shift; for ( k = 0; k < outsize; k++ ) { // Start a new word every 32 bits if ( ((k & 0x1F) == 0) && (k > 0) ) { // Record word *out++ = word ^ flip; // Reset word word = 0; } word |= GET_ith_BIT(in,t) << (k & 0x1F); if (++t == insize) t = 0; } // Record last word in sequence *out++ = word ^ flip; } return(1);}/* * This function writes the midamble of the FIRST user to * the addess pointed by out. The output amplitude is 'amp' and the * midamble index (row of the midamble table) is given by 'mid_index' * The midamble characteristics as the midamble table, the length and the * mapping are contained in the structure pointed by mid. * The output od the function is directly written in out[], without taking * care of the existing values of 'out[]' * * @param mid midamble to build * @param out memory address of the output * @param amp midamble amplitude * @param mid_index midamble index * @return*/int midamble_write( int mid_type, SYMBOL_COMPLEX *out_mid, unsigned int amp, unsigned short mid_index ) { short bit12; int bits=0; int bmask=3; mmx_t midamp, *map, *out = (mmx_t*)out_mid; unsigned int i, j; unsigned int count; midamble_t *mid = &midamble_def[ mid_type ]; // if the current shift is odd if((mid_index*(mid->shift)) & 0x00000001) { // then in the current midamble the first chip is real map = mapping_def[0]; // Copy the midamble amplitude twice in an mmx variable. midamp.d[0] = amp; // midamp = [amp,0,0,amp] (Re and Im; Re first) midamp.d[1] = amp<<16; } else { // Copy the midamble amplitude twice in an mmx variable. midamp.d[0] = amp<<16; // midamp = [0,amp,amp,0] (Im and Re; Im first) midamp.d[1] = amp; // else in the current midamble the first chip is imaginary map = mapping_def[1]; } // in mm3 there is [midamp,0,0,midamp] movq_m2r(midamp,mm3); // mid_index now is the index of the current midamble // in the midamble table (in words) mid_index = ((mid->length+31)>>5)*mid_index; // counts the chips in the midamble count=0; // for all the words-1 in the current midamble for (i=0; i<((mid->length)>>5); i++) { // for each loop it writes 16 mmx_t = 32 cpx samples = 64 real samples // Read in 32 new bits from the midamble table bits = mid->midamble_table[mid_index+i]; for ( j=0; j<16; j++ ) { // extract two chips bit12 = bits & bmask; bits = bits >> 2; // put 64 bit map into register mm0 movq_m2r( map[ bit12 ], mm0 ); // multiply by mm3 (midamp) pmullw_r2r( mm3, mm0 ); // put the result in out movq_r2m( mm0, *out ); out++; } // adds 32 because we have read 32 chips count+=32; } // if there is still a 32-bit word that contains midamble chips if( count != mid->length ) { // Read in the last 32bits from the midamble table bits = mid->midamble_table[mid_index+(mid->length>>5)]; // for each chip in the last word for (i=0; i<((mid->length-count)/2); i++) { bit12 = bits & bmask; bits = bits >> 2; movq_m2r( map[bit12], mm0 ); pmullw_r2r( mm3, mm0 ); movq_r2m( mm0, out[i] ); } } emms(); return 0;}/** * This function is similar to Build_Midamble. * The only difference is that the output of the function * DOES NOT REPLACE the existing data contained in 'out[]', instead * it is summed up with. * This function writes the midamble of the FIRST user to * the addess pointed by out. The output amplitude is 'amp' and the * midamble index (row of the midamble table) is given by 'mid_index' * The midamble characteristics as the midamble table, the length and the * mapping are contained in the structure pointed by mid. * The output od the function is directly written in out[], without taking * care of the existing values of 'out[]' * * @param mid midamble to build * @param out memory address of the output * @param amp midamble amplitude * @param mid_index midamble index * @return */int midamble_add( int mid_type, SYMBOL_COMPLEX *out_mid, unsigned int amp, unsigned short mid_index ) { register short bit12; register int bits=0; register int bmask=3; mmx_t midamp, *map, *out = (mmx_t*)out_mid; unsigned int i, j; unsigned int count; midamble_t *mid = &midamble_def[ mid_type ]; // if the current shift is odd if((mid_index*(mid->shift)) & 0x00000001) { // then in the current midamble the first chip is real map = mapping_def[0]; // Copy the midamble amplitude twice in an mmx variable. midamp.d[0] = amp; // midamp = [amp,0,0,amp] (Re and Im; Re first) midamp.d[1] = amp<<16; } else { // Copy the midamble amplitude twice in an mmx variable. midamp.d[0] = amp<<16; // midamp = [0,amp,amp,0] (Im and Re; Im first) midamp.d[1] = amp; // else in the current midamble the first chip is imaginary map = mapping_def[1]; } // in mm3 there is [midamp,0,0,midamp] movq_m2r(midamp,mm3); // mid_index now is the index of the current midamble // in the midamble table (in words) mid_index = ((mid->length+31)>>5)*mid_index; // counts the chips in the midamble count=0; // for all the words-1 in the current midamble for (i=0; i<((mid->length)>>5); i++) { // for each loop it writes 16 mmx_t = 32 cpx samples = 64 real samples // Read in 32 new bits from the midamble table bits = mid->midamble_table[mid_index+i]; for ( j=0; j<16; j++ ) { // extract two chips bit12 = bits & bmask; bits = bits >> 2; // put 64 bit map into register mm0 movq_m2r( map[ bit12 ], mm0 ); // multiply by mm3 (midamp) pmullw_r2r( mm3, mm0 ); // add the result to out movq_m2r( *out, mm4 ); paddw_r2r( mm0, mm4 ); movq_r2m( mm4, *out ); out++; } // adds 32 because we have read 32 more chips count+=32; } // if there is still a 32-bit word that contains midamble chips if( count != mid->length ) { // Read in the last 32bits from the midamble table bits = mid->midamble_table[mid_index+(mid->length>>5)]; // for each chip in the last word for (i=0; i<((mid->length-count)/2); i++) { bit12 = bits & bmask; bits = bits >> 2; movq_m2r(map[ bit12 ],mm0); pmullw_r2r(mm3,mm0); movq_m2r( *out, mm4 ); paddw_r2r( mm0, mm4 ); movq_r2m( mm4, *out ); } } return 0;}int midamble_get_nbr_channels( int mid_type ) { return midamble_def[ mid_type ].max_channels;}int midamble_get_length( int mid_type ) { return midamble_def[ mid_type ].length;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -