Added scrambling, ratematching and layer mapping tests

master
ismagom 11 years ago
parent bea03bfdd2
commit 67b8cf3ee2

@ -42,6 +42,10 @@ INCLUDE(libLTEPackage) #setup cpack
include(CTest) include(CTest)
set( CTEST_MEMORYCHECK_COMMAND valgrind ) set( CTEST_MEMORYCHECK_COMMAND valgrind )
CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake"
IMMEDIATE @ONLY)
######################################################################## ########################################################################
# Install Dirs # Install Dirs

@ -0,0 +1,15 @@
SET(CTEST_CUSTOM_MEMCHECK_IGNORE
# Ignore memcheck for plots. QT errors
waterfallplot_test
scatterplot_test
realplot_test
complexplot_test
# Ignore these to, they take too lonk
fft_normal
fft_extened
chest_test_all_cellids
)

@ -19,8 +19,9 @@
# and at http://www.gnu.org/licenses/. # and at http://www.gnu.org/licenses/.
# #
################################################################# #################################################################
# TO BE MOVED TO UNIT TESTS # EXAMPLES
################################################################# #################################################################
add_executable(hl_example hl_example.c) add_executable(hl_example hl_example.c)
@ -29,8 +30,13 @@ target_link_libraries(hl_example lte)
add_executable(ll_example ll_example.c) add_executable(ll_example ll_example.c)
target_link_libraries(ll_example lte) target_link_libraries(ll_example lte)
add_executable(synch_test synch_test.c) add_executable(synch_file synch_file.c)
target_link_libraries(synch_test lte) target_link_libraries(synch_file lte)
#################################################################
# TO BE MOVED TO UNIT TESTS
#################################################################
add_executable(mib_test mib_test.c) add_executable(mib_test mib_test.c)
target_link_libraries(mib_test lte) target_link_libraries(mib_test lte)
@ -47,26 +53,26 @@ LIST(FIND OPTIONAL_LIBS graphics GRAPHICS_FIND)
# These two can be compiled without UHD or graphics support # These two can be compiled without UHD or graphics support
################################################################# #################################################################
add_executable(mib_track mib_track.c) add_executable(pbch_ue pbch_ue.c)
target_link_libraries(mib_track lte) target_link_libraries(pbch_ue lte)
add_executable(enodeb_bch enodeb_bch.c) add_executable(pbch_enodeb pbch_enodeb.c)
target_link_libraries(enodeb_bch lte) target_link_libraries(pbch_enodeb lte)
IF(${CUHD_FIND} EQUAL -1) IF(${CUHD_FIND} EQUAL -1)
SET_TARGET_PROPERTIES(mib_track PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD") SET_TARGET_PROPERTIES(pbch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
SET_TARGET_PROPERTIES(enodeb_bch PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD") SET_TARGET_PROPERTIES(pbch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
ELSE(${CUHD_FIND} EQUAL -1) ELSE(${CUHD_FIND} EQUAL -1)
target_link_libraries(mib_track cuhd) target_link_libraries(pbch_ue cuhd)
target_link_libraries(enodeb_bch cuhd) target_link_libraries(pbch_enodeb cuhd)
ENDIF(${CUHD_FIND} EQUAL -1) ENDIF(${CUHD_FIND} EQUAL -1)
IF(${GRAPHICS_FIND} EQUAL -1) IF(${GRAPHICS_FIND} EQUAL -1)
SET_TARGET_PROPERTIES(mib_track PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS") SET_TARGET_PROPERTIES(pbch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
SET_TARGET_PROPERTIES(enodeb_bch PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS") SET_TARGET_PROPERTIES(pbch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
ELSE(${GRAPHICS_FIND} EQUAL -1) ELSE(${GRAPHICS_FIND} EQUAL -1)
target_link_libraries(mib_track graphics) target_link_libraries(pbch_ue graphics)
target_link_libraries(enodeb_bch graphics) target_link_libraries(pbch_enodeb graphics)
ENDIF(${GRAPHICS_FIND} EQUAL -1) ENDIF(${GRAPHICS_FIND} EQUAL -1)
@ -77,14 +83,14 @@ ENDIF(${GRAPHICS_FIND} EQUAL -1)
IF(${CUHD_FIND} GREATER -1) IF(${CUHD_FIND} GREATER -1)
add_executable(rssi_scan_usrp rssi_scan_usrp.c) add_executable(scan_rssi scan_rssi.c)
target_link_libraries(rssi_scan_usrp lte cuhd ) target_link_libraries(scan_rssi lte cuhd )
add_executable(pss_scan_usrp pss_scan_usrp.c) add_executable(scan_pss scan_pss.c)
target_link_libraries(pss_scan_usrp lte cuhd ) target_link_libraries(scan_pss lte cuhd )
add_executable(mib_scan_usrp mib_scan_usrp.c) add_executable(scan_mib scan_mib.c)
target_link_libraries(mib_scan_usrp lte cuhd ) target_link_libraries(scan_mib lte cuhd )
MESSAGE(STATUS " UHD examples will be installed.") MESSAGE(STATUS " UHD examples will be installed.")

@ -37,20 +37,18 @@ char *input_file_name;
char *output_file_name="abs_corr.txt"; char *output_file_name="abs_corr.txt";
int nof_slots=100, frame_length=9600, symbol_sz=128; int nof_slots=100, frame_length=9600, symbol_sz=128;
float corr_peak_threshold=25.0; float corr_peak_threshold=25.0;
int file_binary = 0;
int out_N_id_2 = 0, force_N_id_2=-1; int out_N_id_2 = 0, force_N_id_2=-1;
#define CFO_AUTO -9999.0 #define CFO_AUTO -9999.0
float force_cfo = CFO_AUTO; float force_cfo = CFO_AUTO;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [onlt] -i input_file\n", prog); printf("Usage: %s [olntsNfc] -i input_file\n", prog);
printf("\t-o output_file [Default %s]\n", output_file_name); printf("\t-o output_file [Default %s]\n", output_file_name);
printf("\t-l frame_length [Default %d]\n", frame_length); printf("\t-l frame_length [Default %d]\n", frame_length);
printf("\t-n number of frames [Default %d]\n", nof_slots); printf("\t-n number of frames [Default %d]\n", nof_slots);
printf("\t-t correlation threshold [Default %g]\n", corr_peak_threshold); printf("\t-t correlation threshold [Default %g]\n", corr_peak_threshold);
printf("\t-s symbol_sz [Default %d]\n", symbol_sz); printf("\t-s symbol_sz [Default %d]\n", symbol_sz);
printf("\t-b Input files is binary [Default %s]\n", file_binary?"yes":"no");
printf("\t-N out_N_id_2 [Default %d]\n", out_N_id_2); printf("\t-N out_N_id_2 [Default %d]\n", out_N_id_2);
printf("\t-f force_N_id_2 [Default %d]\n", force_N_id_2); printf("\t-f force_N_id_2 [Default %d]\n", force_N_id_2);
printf("\t-c force_cfo [Default disabled]\n"); printf("\t-c force_cfo [Default disabled]\n");
@ -58,7 +56,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "ionltsbNfc")) != -1) { while ((opt = getopt(argc, argv, "ionltsNfc")) != -1) {
switch(opt) { switch(opt) {
case 'i': case 'i':
input_file_name = argv[optind]; input_file_name = argv[optind];
@ -78,9 +76,6 @@ void parse_args(int argc, char **argv) {
case 's': case 's':
symbol_sz = atof(argv[optind]); symbol_sz = atof(argv[optind]);
break; break;
case 'b':
file_binary = 1;
break;
case 'N': case 'N':
out_N_id_2 = atoi(argv[optind]); out_N_id_2 = atoi(argv[optind]);
break; break;
@ -130,12 +125,11 @@ int main(int argc, char **argv) {
gettimeofday(&tdata[1], NULL); gettimeofday(&tdata[1], NULL);
printf("Initializing...");fflush(stdout); printf("Initializing...");fflush(stdout);
data_type_t type = file_binary?COMPLEX_FLOAT_BIN:COMPLEX_FLOAT; if (filesource_init(&fsrc, input_file_name, COMPLEX_FLOAT_BIN)) {
if (filesource_init(&fsrc, input_file_name, type)) {
fprintf(stderr, "Error opening file %s\n", input_file_name); fprintf(stderr, "Error opening file %s\n", input_file_name);
exit(-1); exit(-1);
} }
if (filesink_init(&fsink, output_file_name, type)) { if (filesink_init(&fsink, output_file_name, COMPLEX_FLOAT_BIN)) {
fprintf(stderr, "Error opening file %s\n", output_file_name); fprintf(stderr, "Error opening file %s\n", output_file_name);
exit(-1); exit(-1);
} }

@ -34,8 +34,8 @@
#define MAX_PORTS 4 #define MAX_PORTS 4
#define MAX_PORTS_CTRL 4 #define MAX_PORTS_CTRL 4
#define MAX_LAYERS 4 #define MAX_LAYERS 8
#define MAX_CODEWORDS 4 #define MAX_CODEWORDS 2
typedef enum {CPNORM, CPEXT} lte_cp_t; typedef enum {CPNORM, CPEXT} lte_cp_t;
@ -85,7 +85,7 @@ int lte_voffset(int symbol_id, int cell_id, int nof_ports);
typedef enum { typedef enum {
TX_DIVERSITY, SPATIAL_MULTIPLEX SINGLE_ANTENNA,TX_DIVERSITY, SPATIAL_MULTIPLEX
} mimo_type_t; } mimo_type_t;
@ -103,6 +103,8 @@ int lte_band_get_fd_band(int band, lte_earfcn_t *earfcn, int earfcn_start, int e
int lte_band_get_fd_band_all(int band, lte_earfcn_t *earfcn, int max_nelems); int lte_band_get_fd_band_all(int band, lte_earfcn_t *earfcn, int max_nelems);
int lte_band_get_fd_region(enum band_geographical_area region, lte_earfcn_t *earfcn, int max_elems); int lte_band_get_fd_region(enum band_geographical_area region, lte_earfcn_t *earfcn, int max_elems);
int lte_str2mimotype(char *mimo_type_str, mimo_type_t *type);
char *lte_mimotype2str(mimo_type_t type);
#endif #endif

@ -31,14 +31,23 @@
typedef _Complex float cf_t; typedef _Complex float cf_t;
/* Generates the vector of data symbols "d" based on the vector of layer-mapped symbols "x" /* Generates the vector of layer-mapped symbols "x" based on the vector of data symbols "d"
*/ */
void layermap_decode(cf_t *x[MAX_LAYERS], cf_t *d[MAX_CODEWORDS], int nof_layers, int nof_cw, int layermap_single(cf_t *d, cf_t *x, int nof_symbols);
int nof_layer_symbols, mimo_type_t type); int layermap_diversity(cf_t *d, cf_t *x[MAX_LAYERS], int nof_layers, int nof_symbols);
int layermap_multiplex(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_cw, int nof_layers,
int nof_symbols[MAX_CODEWORDS]);
int layermap_type(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_cw, int nof_layers,
int nof_symbols[MAX_CODEWORDS], mimo_type_t type);
/* Generates the vector of layer-mapped symbols "x" based on the vector of data symbols "d"
/* Generates the vector of data symbols "d" based on the vector of layer-mapped symbols "x"
*/ */
void layermap_encode(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_layers, int nof_cw, int layerdemap_single(cf_t *x, cf_t *d, int nof_symbols);
int nof_symbols, mimo_type_t type); int layerdemap_diversity(cf_t *x[MAX_LAYERS], cf_t *d, int nof_layers, int nof_layer_symbols);
int layerdemap_multiplex(cf_t *x[MAX_LAYERS], cf_t *d[MAX_CODEWORDS], int nof_layers, int nof_cw,
int nof_layer_symbols, int nof_symbols[MAX_CODEWORDS]);
int layerdemap_type(cf_t *x[MAX_LAYERS], cf_t *d[MAX_CODEWORDS], int nof_layers, int nof_cw,
int nof_layer_symbols, int nof_symbols[MAX_CODEWORDS], mimo_type_t type);
#endif #endif

@ -36,15 +36,21 @@ typedef _Complex float cf_t;
* resources on each of the antenna ports. * resources on each of the antenna ports.
*/ */
/* Estimates the vector "x" based on the received signal "y" and the channel estimates "ce"
*/
void precoding_decode(cf_t *y[MAX_PORTS], cf_t *ce[MAX_PORTS],
cf_t *x[MAX_LAYERS], int nof_ports, int nof_symbols,
mimo_type_t type);
/* Generates the vector "y" from the input vector "x" /* Generates the vector "y" from the input vector "x"
*/ */
void precoding_encode(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_ports, int precoding_single(cf_t *x, cf_t *y, int nof_symbols);
int precoding_diversity(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_ports, int nof_symbols);
int precoding_type(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_layers, int nof_ports,
int nof_symbols, mimo_type_t type); int nof_symbols, mimo_type_t type);
/* Estimates the vector "x" based on the received signal "y" and the channel estimates "ce"
*/
int predecoding_single_zf(cf_t *y, cf_t *ce, cf_t *x, int nof_symbols);
int predecoding_diversity_zf(cf_t *y[MAX_PORTS], cf_t *ce[MAX_PORTS],
cf_t *x[MAX_LAYERS], int nof_ports, int nof_symbols);
int predecoding_type(cf_t *y[MAX_PORTS], cf_t *ce[MAX_PORTS],
cf_t *x[MAX_LAYERS], int nof_ports, int nof_layers, int nof_symbols,
mimo_type_t type);
#endif /* PRECODING_H_ */ #endif /* PRECODING_H_ */

@ -42,8 +42,8 @@ typedef struct {
void demod_hard_init(demod_hard_t* q); void demod_hard_init(demod_hard_t* q);
void demod_hard_table(demod_hard_t* q, enum modem_std table); void demod_hard_table_set(demod_hard_t* q, enum modem_std table);
int demod_hard_demodulate(demod_hard_t* q, const cf_t* symbols, char *bits, int nsymbols); int demod_hard_demodulate(demod_hard_t* q, cf_t* symbols, char *bits, int nsymbols);

@ -27,5 +27,6 @@ ADD_EXECUTABLE(chest_test chest_test.c)
TARGET_LINK_LIBRARIES(chest_test lte) TARGET_LINK_LIBRARIES(chest_test lte)
ADD_TEST(chest_test_all_cellids chest_test) ADD_TEST(chest_test_all_cellids chest_test)
ADD_TEST(chest_test_cellid chest_test -c 1)

@ -71,6 +71,9 @@ int lte_fft_init_(lte_fft_t *q, lte_cp_t cp_type, int nof_prb, dft_dir_t dir) {
void lte_fft_free_(lte_fft_t *q) { void lte_fft_free_(lte_fft_t *q) {
dft_plan_free(&q->fft_plan); dft_plan_free(&q->fft_plan);
if (q->tmp) {
free(q->tmp);
}
bzero(q, sizeof(lte_fft_t)); bzero(q, sizeof(lte_fft_t));
} }

@ -134,6 +134,30 @@ struct lte_band lte_bands[NOF_LTE_BANDS] = {
}; };
#define EOF_BAND 9919 #define EOF_BAND 9919
int lte_str2mimotype(char *mimo_type_str, mimo_type_t *type) {
if (!strcmp(mimo_type_str, "single")) {
*type = SINGLE_ANTENNA;
} else if (!strcmp(mimo_type_str, "diversity")) {
*type = TX_DIVERSITY;
} else if (!strcmp(mimo_type_str, "multiplex")) {
*type = SPATIAL_MULTIPLEX;
} else {
return -1;
}
return 0;
}
char *lte_mimotype2str(mimo_type_t type) {
switch(type) {
case SINGLE_ANTENNA:
return "single";
case TX_DIVERSITY:
return "diversity";
case SPATIAL_MULTIPLEX:
return "multiplex";
}
}
float get_fd(struct lte_band *band, int earfcn) { float get_fd(struct lte_band *band, int earfcn) {
return band->fd_low_mhz + 0.1*(earfcn - band->earfcn_offset); return band->fd_low_mhz + 0.1*(earfcn - band->earfcn_offset);
} }

@ -25,10 +25,11 @@
* *
*/ */
#include <strings.h>
#include "lte/common/base.h" #include "lte/common/base.h"
#include "lte/common/sequence.h" #include "lte/common/sequence.h"
int sequence_pbch(sequence_t *seq, lte_cp_t cp, int cell_id) { int sequence_pbch(sequence_t *seq, lte_cp_t cp, int cell_id) {
bzero(seq, sizeof(sequence_t));
return sequence_LTEPRS(seq, CP_ISNORM(cp)?1920:1728, cell_id); return sequence_LTEPRS(seq, CP_ISNORM(cp)?1920:1728, cell_id);
} }

@ -0,0 +1,34 @@
#
# Copyright 2012-2013 The libLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the libLTE library.
#
# libLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# libLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
########################################################################
# FFT TEST
########################################################################
ADD_EXECUTABLE(fft_test fft_test.c)
TARGET_LINK_LIBRARIES(fft_test lte)
ADD_TEST(fft_normal fft_test)
ADD_TEST(fft_extended fft_test -e)
ADD_TEST(fft_normal_single fft_test -n 6)
ADD_TEST(fft_extended_single fft_test -e -n 6)

@ -0,0 +1,141 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include "lte.h"
int nof_prb = -1;
lte_cp_t cp = CPNORM;
void usage(char *prog) {
printf("Usage: %s\n", prog);
printf("\t-n nof_prb [Default All]\n");
printf("\t-e extended cyclic prefix [Default Normal]\n");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "ne")) != -1) {
switch (opt) {
case 'n':
nof_prb = atoi(argv[optind]);
break;
case 'e':
cp = CPEXT;
break;
default:
usage(argv[0]);
exit(-1);
}
}
}
int main(int argc, char **argv) {
lte_fft_t fft, ifft;
cf_t *input, *outfft, *outifft;
float mse;
int n_prb, max_prb, n_re;
int i;
parse_args(argc, argv);
if (nof_prb == -1) {
n_prb = 6;
max_prb = 100;
} else {
n_prb = nof_prb;
max_prb = nof_prb;
}
while(n_prb <= max_prb) {
n_re = CP_NSYMB(cp) * n_prb * RE_X_RB;
printf("Running test for %d PRB, %d RE... ", n_prb, n_re);fflush(stdout);
input = malloc(sizeof(cf_t) * n_re);
if (!input) {
perror("malloc");
exit(-1);
}
outfft = malloc(sizeof(cf_t) * SLOT_LEN_CPNORM(lte_symbol_sz(n_prb)));
if (!outfft) {
perror("malloc");
exit(-1);
}
outifft = malloc(sizeof(cf_t) * n_re);
if (!outifft) {
perror("malloc");
exit(-1);
}
if (lte_fft_init(&fft, cp, n_prb)) {
fprintf(stderr, "Error initializing FFT\n");
exit(-1);
}
if (lte_ifft_init(&ifft, cp, n_prb)) {
fprintf(stderr, "Error initializing iFFT\n");
exit(-1);
}
for (i=0;i<n_re;i++) {
input[i] = 100 * ((float) rand()/RAND_MAX + (float) I*rand()/RAND_MAX);
}
lte_ifft_run(&ifft, input, outfft);
lte_fft_run(&fft, outfft, outifft);
/* compute MSE */
mse = 0;
for (i=0;i<n_re;i++) {
mse += cabsf(input[i] - outifft[i]);
}
printf("MSE=%f\n", mse);
if (mse >= 0.05) {
printf("MSE too large\n");
exit(-1);
}
lte_fft_free(&fft);
lte_ifft_free(&ifft);
free(input);
free(outfft);
free(outifft);
n_prb++;
}
fftwf_cleanup();
exit(0);
}

@ -33,46 +33,182 @@
#include "lte/common/base.h" #include "lte/common/base.h"
#include "lte/mimo/layermap.h" #include "lte/mimo/layermap.h"
/* Generates the vector of data symbols "d" based on the vector of layer-mapped symbols "x"
int layermap_single(cf_t *d, cf_t *x, int nof_symbols) {
memcpy(x, d, sizeof(cf_t) * nof_symbols);
return nof_symbols;
}
int layermap_diversity(cf_t *d, cf_t *x[MAX_LAYERS], int nof_layers, int nof_symbols) {
int i, j;
for (i=0;i<nof_symbols/nof_layers;i++) {
for (j=0;j<nof_layers;j++) {
x[j][i] = d[nof_layers*i+j];
}
}
return i;
}
int layermap_multiplex(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_cw, int nof_layers,
int nof_symbols[MAX_CODEWORDS]) {
if (nof_cw == 1) {
return layermap_diversity(d[0], x, nof_layers, nof_symbols[0]);
} else {
int n[2];
n[0] = nof_layers / nof_cw;
n[1] = nof_layers - n[0];
if (nof_symbols[0] / n[0] == nof_symbols[1] / n[1]) {
layermap_diversity(d[0], x, n[0], nof_symbols[0]);
layermap_diversity(d[1], &x[n[0]], n[1], nof_symbols[1]);
return nof_symbols[0] / n[0];
} else {
fprintf(stderr, "Number of symbols in codewords 0 and 1 is not consistent (%d, %d)\n",
nof_symbols[0], nof_symbols[1]);
return -1;
}
}
return 0;
}
/* Layer mapping generates the vector of layer-mapped symbols "x" based on the vector of data symbols "d"
* Based on 36.211 6.3.3
* Returns the number of symbols per layer (M_symb^layer in the specs)
*/ */
void layermap_decode(cf_t *x[MAX_LAYERS], cf_t *d[MAX_CODEWORDS], int nof_layers, int nof_cw, int layermap_type(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_cw, int nof_layers,
int nof_layer_symbols, mimo_type_t type) { int nof_symbols[MAX_CODEWORDS], mimo_type_t type) {
int i; if (nof_cw > MAX_CODEWORDS) {
fprintf(stderr, "Maximum number of codewords is %d (nof_cw=%d)\n", MAX_CODEWORDS, nof_cw);
return -1;
}
if (nof_layers > MAX_LAYERS) {
fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers);
return -1;
}
if (nof_layers < nof_cw) {
fprintf(stderr, "Number of codewords must be lower or equal than number of layers\n");
return -1;
}
switch(nof_layers) {
case 1:
memcpy(d[0], x[0], nof_layer_symbols * sizeof(cf_t));
break;
case 2:
switch(type) { switch(type) {
case TX_DIVERSITY: case SINGLE_ANTENNA:
for (i=0;i<nof_layer_symbols;i++) { if (nof_cw == 1 && nof_layers == 1) {
d[0][2*i] = x[0][i]; return layermap_single(x[0], d[0], nof_symbols[0]);
d[0][2*i+1] = x[1][i]; } else {
fprintf(stderr, "Number of codewords and layers must be 1 for transmission on single antenna ports\n");
return -1;
} }
break; break;
default: case TX_DIVERSITY:
printf("Error: Unsupported transmit mode\n"); if (nof_cw == 1) {
if (nof_layers == 2 || nof_layers == 4) {
return layermap_diversity(d[0], x, nof_layers, nof_symbols[0]);
} else {
fprintf(stderr, "Number of layers must be 2 or 4 for transmit diversity\n");
return -1;
}
} else {
fprintf(stderr, "Number of codewords must be 1 for transmit diversity\n");
return -1;
} }
break; break;
default: case SPATIAL_MULTIPLEX:
printf("Error: Unsupported nof_ports=%d\n", nof_layers); return layermap_multiplex(d, x, nof_cw, nof_layers, nof_symbols);
return; break;
}
return 0;
}
int layerdemap_single(cf_t *x, cf_t *d, int nof_symbols) {
memcpy(d, x, sizeof(cf_t) * nof_symbols);
return nof_symbols;
}
int layerdemap_diversity(cf_t *x[MAX_LAYERS], cf_t *d, int nof_layers, int nof_layer_symbols) {
int i, j;
for (i=0;i<nof_layer_symbols;i++) {
for (j=0;j<nof_layers;j++) {
d[nof_layers*i+j] = x[j][i];
}
}
return nof_layer_symbols * nof_layers;
}
int layerdemap_multiplex(cf_t *x[MAX_LAYERS], cf_t *d[MAX_CODEWORDS], int nof_layers, int nof_cw,
int nof_layer_symbols, int nof_symbols[MAX_CODEWORDS]) {
if (nof_cw == 1) {
return layerdemap_diversity(x, d[0], nof_layers, nof_layer_symbols);
} else {
int n[2];
n[0] = nof_layers / nof_cw;
n[1] = nof_layers - n[0];
nof_symbols[0] = n[0] * nof_layer_symbols;
nof_symbols[1] = n[1] * nof_layer_symbols;
nof_symbols[0] = layerdemap_diversity(x, d[0], n[0], nof_layer_symbols);
nof_symbols[1] = layerdemap_diversity(&x[n[0]], d[1], n[1], nof_layer_symbols);
} }
return 0;
} }
/* Generates the vector of layer-mapped symbols "x" based on the vector of data symbols "d" /* Generates the vector of data symbols "d" based on the vector of layer-mapped symbols "x"
* Based on 36.211 6.3.3
* Returns 0 on ok and saves the number of symbols per codeword (M_symb^(q) in the specs) in
* nof_symbols. Returns -1 on error
*/ */
void layermap_encode(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_layers, int nof_cw, int layerdemap_type(cf_t *x[MAX_LAYERS], cf_t *d[MAX_CODEWORDS], int nof_layers, int nof_cw,
int nof_symbols, mimo_type_t type) { int nof_layer_symbols, int nof_symbols[MAX_CODEWORDS], mimo_type_t type) {
switch(nof_layers) {
case 1: if (nof_cw > MAX_CODEWORDS) {
memcpy(x[0], d[0], nof_symbols * sizeof(cf_t)); fprintf(stderr, "Maximum number of codewords is %d (nof_cw=%d)\n", MAX_CODEWORDS, nof_cw);
break; return -1;
default: }
printf("Error: Unsupported nof_ports=%d\n", nof_layers); if (nof_layers > MAX_LAYERS) {
return; fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers);
return -1;
} }
if (nof_layers < nof_cw) {
fprintf(stderr, "Number of codewords must be lower or equal than number of layers\n");
return -1;
} }
switch(type) {
case SINGLE_ANTENNA:
if (nof_cw == 1 && nof_layers == 1) {
nof_symbols[0] = layerdemap_single(x[0], d[0], nof_layer_symbols);
nof_symbols[1] = 0;
} else {
fprintf(stderr, "Number of codewords and layers must be 1 for transmission on single antenna ports\n");
return -1;
}
break;
case TX_DIVERSITY:
if (nof_cw == 1) {
if (nof_layers == 2 || nof_layers == 4) {
nof_symbols[0] = layerdemap_diversity(x, d[0], nof_layers, nof_layer_symbols);
nof_symbols[1] = 0;
} else {
fprintf(stderr, "Number of layers must be 2 or 4 for transmit diversity\n");
return -1;
}
} else {
fprintf(stderr, "Number of codewords must be 1 for transmit diversity\n");
return -1;
}
break;
case SPATIAL_MULTIPLEX:
return layerdemap_multiplex(x, d, nof_layers, nof_cw, nof_layer_symbols, nof_symbols);
break;
}
return 0;
}

@ -31,28 +31,87 @@
#include <assert.h> #include <assert.h>
#include <complex.h> #include <complex.h>
#include <string.h> #include <string.h>
#include <math.h>
#include "lte/common/base.h" #include "lte/common/base.h"
#include "lte/mimo/precoding.h" #include "lte/mimo/precoding.h"
#include "lte/utils/vector.h" #include "lte/utils/vector.h"
int precoding_single(cf_t *x, cf_t *y, int nof_symbols) {
memcpy(y, x, nof_symbols * sizeof(cf_t));
return nof_symbols;
}
int precoding_diversity(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_ports, int nof_symbols) {
int i;
if (nof_ports == 2) {
/* FIXME: Use VOLK here */
for (i=0;i<nof_symbols;i++) {
y[0][2*i] = (crealf(x[0][i]) + I * cimagf(x[0][i]))/sqrtf(2);
y[1][2*i] = (-crealf(x[1][i]) + I * cimagf(x[1][i]))/sqrtf(2);
y[0][2*i+1] = (crealf(x[1][i]) + I * cimagf(x[1][i]))/sqrtf(2);
y[1][2*i+1] = (crealf(x[0][i]) + I * cimagf(x[0][i]))/sqrtf(2);
}
return i;
} else if (nof_ports == 4) {
fprintf(stderr, "Error not implemented\n");
return -1;
} else {
fprintf(stderr, "Number of ports must be 2 or 4 for transmit diversity\n");
return -1;
}
}
/* 36.211 v10.3.0 Section 6.3.4 */ /* 36.211 v10.3.0 Section 6.3.4 */
void precoding_decode(cf_t *y[MAX_PORTS], cf_t *ce[MAX_PORTS], int precoding_type(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_layers, int nof_ports, int nof_symbols,
cf_t *x[MAX_LAYERS], int nof_ports, int nof_symbols, mimo_type_t type) { mimo_type_t type) {
int i; if (nof_ports > MAX_PORTS) {
cf_t h0, h1, r0, r1; fprintf(stderr, "Maximum number of ports is %d (nof_ports=%d)\n", MAX_PORTS, nof_ports);
float hh; return -1;
}
if (nof_layers > MAX_LAYERS) {
fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers);
return -1;
}
switch(nof_ports) {
case 1:
vec_div_ccc(y[0], ce[0], x[0], nof_symbols);
break;
case 2:
switch(type) { switch(type) {
case SINGLE_ANTENNA:
if (nof_ports == 1 && nof_layers == 1) {
return precoding_single(x[0], y[0], nof_symbols);
} else {
fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports\n");
return -1;
}
break;
case TX_DIVERSITY: case TX_DIVERSITY:
if (nof_ports == nof_layers) {
return precoding_diversity(y, x, nof_ports, nof_symbols);
} else {
fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n");
return -1;
}
case SPATIAL_MULTIPLEX:
fprintf(stderr, "Spatial multiplexing not supported\n");
return -1;
}
return 0;
}
/* ZF detector */
int predecoding_single_zf(cf_t *y, cf_t *ce, cf_t *x, int nof_symbols) {
vec_div_ccc(y, ce, x, nof_symbols);
return nof_symbols;
}
/* ZF detector */
int predecoding_diversity_zf(cf_t *y[MAX_PORTS], cf_t *ce[MAX_PORTS],
cf_t *x[MAX_LAYERS], int nof_ports, int nof_symbols) {
int i;
cf_t h0, h1, r0, r1;
float hh;
if (nof_ports == 2) {
/* FIXME: Use VOLK here */ /* FIXME: Use VOLK here */
// 6.3.4.3
for (i=0;i<nof_symbols/2;i++) { for (i=0;i<nof_symbols/2;i++) {
h0 = ce[0][2*i]; h0 = ce[0][2*i];
h1 = ce[1][2*i]; h1 = ce[1][2*i];
@ -62,25 +121,51 @@ void precoding_decode(cf_t *y[MAX_PORTS], cf_t *ce[MAX_PORTS],
x[0][i] = (conj(h0)*r0 + h1*conj(r1))/hh; x[0][i] = (conj(h0)*r0 + h1*conj(r1))/hh;
x[1][i] = (h0*conj(r1) - h1*conj(r0))/hh; x[1][i] = (h0*conj(r1) - h1*conj(r0))/hh;
} }
break; return i;
default: } else if (nof_ports == 4) {
printf("Error: Unsupported transmit mode\n"); fprintf(stderr, "Error not implemented\n");
return -1;
} else {
fprintf(stderr, "Number of ports must be 2 or 4 for transmit diversity\n");
return -1;
} }
break;
default:
printf("Error: Unsupported nof_ports=%d\n", nof_ports);
return;
} }
/* 36.211 v10.3.0 Section 6.3.4 */
int predecoding_type(cf_t *y[MAX_PORTS], cf_t *ce[MAX_PORTS],
cf_t *x[MAX_LAYERS], int nof_ports, int nof_layers, int nof_symbols, mimo_type_t type) {
if (nof_ports > MAX_PORTS) {
fprintf(stderr, "Maximum number of ports is %d (nof_ports=%d)\n", MAX_PORTS, nof_ports);
return -1;
}
if (nof_layers > MAX_LAYERS) {
fprintf(stderr, "Maximum number of layers is %d (nof_layers=%d)\n", MAX_LAYERS, nof_layers);
return -1;
} }
void precoding_encode(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_ports, int nof_symbols,
mimo_type_t type) { switch(type) {
switch(nof_ports) { case SINGLE_ANTENNA:
case 1: if (nof_ports == 1 && nof_layers == 1) {
memcpy(y[0], x[0], nof_symbols * sizeof(cf_t)); return predecoding_single_zf(y[0], ce[0], x[0], nof_symbols);
} else{
fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports\n");
return -1;
}
break; break;
default: case TX_DIVERSITY:
printf("Error: Unsupported nof_ports=%d\n", nof_ports); if (nof_ports == nof_layers) {
return; return predecoding_diversity_zf(y, ce, x, nof_ports, nof_symbols);
} else {
fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n");
return -1;
} }
break;
case SPATIAL_MULTIPLEX:
fprintf(stderr, "Spatial multiplexing not supported\n");
return -1;
} }
return 0;
}

@ -0,0 +1,65 @@
#
# Copyright 2012-2013 The libLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the libLTE library.
#
# libLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# libLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
########################################################################
# LAYER MAPPING TEST
########################################################################
ADD_EXECUTABLE(layermap_test layermap_test.c)
TARGET_LINK_LIBRARIES(layermap_test lte)
ADD_TEST(layermap_single layermap_test -n 1000 -m single -c 1 -l 1)
ADD_TEST(layermap_diversity_2 layermap_test -n 1000 -m diversity -c 1 -l 2)
ADD_TEST(layermap_diversity_4 layermap_test -n 1000 -m diversity -c 1 -l 4)
ADD_TEST(layermap_multiplex_11 layermap_test -n 1000 -m multiplex -c 1 -l 1)
ADD_TEST(layermap_multiplex_12 layermap_test -n 1000 -m multiplex -c 1 -l 2)
ADD_TEST(layermap_multiplex_13 layermap_test -n 1002 -m multiplex -c 1 -l 3)
ADD_TEST(layermap_multiplex_14 layermap_test -n 1000 -m multiplex -c 1 -l 4)
ADD_TEST(layermap_multiplex_15 layermap_test -n 1000 -m multiplex -c 1 -l 5)
ADD_TEST(layermap_multiplex_16 layermap_test -n 1002 -m multiplex -c 1 -l 6)
ADD_TEST(layermap_multiplex_17 layermap_test -n 994 -m multiplex -c 1 -l 7)
ADD_TEST(layermap_multiplex_18 layermap_test -n 1000 -m multiplex -c 1 -l 8)
ADD_TEST(layermap_multiplex_22 layermap_test -n 1000 -m multiplex -c 2 -l 2)
ADD_TEST(layermap_multiplex_23 layermap_test -n 1002 -m multiplex -c 2 -l 3)
ADD_TEST(layermap_multiplex_24 layermap_test -n 1000 -m multiplex -c 2 -l 4)
ADD_TEST(layermap_multiplex_25 layermap_test -n 1002 -m multiplex -c 2 -l 5)
ADD_TEST(layermap_multiplex_26 layermap_test -n 1002 -m multiplex -c 2 -l 6)
ADD_TEST(layermap_multiplex_27 layermap_test -n 1000 -m multiplex -c 2 -l 7)
ADD_TEST(layermap_multiplex_28 layermap_test -n 1000 -m multiplex -c 2 -l 8)
########################################################################
# LAYER MAPPING TEST
########################################################################
#ADD_EXECUTABLE(precoding_test precoding_test.c)
#TARGET_LINK_LIBRARIES(precoding_test lte)

@ -0,0 +1,163 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include "lte.h"
int nof_symbols = 1000;
int nof_cw = 1, nof_layers = 1;
char *mimo_type_name = NULL;
void usage(char *prog) {
printf("Usage: %s -m [single|diversity|multiplex] -c [nof_cw] -l [nof_layers]\n", prog);
printf("\t-n num_symbols [Default %d]\n", nof_symbols);
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "mcln")) != -1) {
switch (opt) {
case 'n':
nof_symbols = atoi(argv[optind]);
break;
case 'c':
nof_cw = atoi(argv[optind]);
break;
case 'l':
nof_layers = atoi(argv[optind]);
break;
case 'm':
mimo_type_name = argv[optind];
break;
default:
usage(argv[0]);
exit(-1);
}
}
if (!mimo_type_name) {
usage(argv[0]);
exit(-1);
}
}
int main(int argc, char **argv) {
int i, j, num_errors, symbols_layer;
cf_t *d[MAX_CODEWORDS], *x[MAX_LAYERS], *dp[MAX_CODEWORDS];
mimo_type_t type;
int nof_symb_cw[MAX_CODEWORDS];
int n[2];
parse_args(argc, argv);
if (lte_str2mimotype(mimo_type_name, &type)) {
fprintf(stderr, "Invalid MIMO type %s\n", mimo_type_name);
exit(-1);
}
if (nof_cw > 1) {
n[0] = nof_layers / nof_cw;
n[1] = nof_layers - n[0];
nof_symb_cw[0] = nof_symbols * n[0];
nof_symb_cw[1] = nof_symbols * n[1];
} else {
nof_symb_cw[0] = nof_symbols;
nof_symb_cw[1] = 0;
}
for (i=0;i<nof_cw;i++) {
d[i] = malloc(sizeof(cf_t) * nof_symb_cw[i]);
if (!d[i]) {
perror("malloc");
exit(-1);
}
dp[i] = malloc(sizeof(cf_t) * nof_symb_cw[i]);
if (!dp[i]) {
perror("malloc");
exit(-1);
}
}
for (i=0;i<nof_layers;i++) {
x[i] = malloc(sizeof(cf_t) * nof_symbols);
if (!x[i]) {
perror("malloc");
exit(-1);
}
}
/* generate random data */
for (i=0;i<nof_cw;i++) {
for (j=0;j<nof_symb_cw[i];j++) {
d[i][j] = 100 * (rand()/RAND_MAX + I*rand()/RAND_MAX);
}
}
/* layer encode */
if ((symbols_layer = layermap_type(d, x, nof_cw, nof_layers, nof_symb_cw, type)) < 0) {
fprintf(stderr, "Error layer mapper encoder\n");
exit(-1);
}
/* layer decode */
if (layerdemap_type(x, dp, nof_layers, nof_cw, nof_symbols/nof_layers, nof_symb_cw, type) < 0) {
fprintf(stderr, "Error layer mapper encoder\n");
exit(-1);
}
/* check errors */
num_errors = 0;
for (i=0;i<nof_cw;i++) {
for (j=0;j<nof_symb_cw[i];j++) {
if (d[i][j] != dp[i][j]) {
num_errors++;
}
}
}
for (i=0;i<nof_cw;i++) {
free(d[i]);
free(dp[i]);
}
for (i=0;i<nof_layers;i++) {
free(x[i]);
}
if (num_errors) {
printf("%d Errors\n", num_errors);
exit(-1);
} else {
printf("Ok\n");
exit(0);
}
}

@ -0,0 +1,163 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include "lte.h"
int nof_symbols = 1000;
int nof_cw = 1, nof_layers = 1;
char *mimo_type_name = NULL;
void usage(char *prog) {
printf("Usage: %s -m [single|diversity|multiplex] -c [nof_cw] -l [nof_layers]\n", prog);
printf("\t-n num_symbols [Default %d]\n", nof_symbols);
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "mcln")) != -1) {
switch (opt) {
case 'n':
nof_symbols = atoi(argv[optind]);
break;
case 'c':
nof_cw = atoi(argv[optind]);
break;
case 'l':
nof_layers = atoi(argv[optind]);
break;
case 'm':
mimo_type_name = argv[optind];
break;
default:
usage(argv[0]);
exit(-1);
}
}
if (!mimo_type_name) {
usage(argv[0]);
exit(-1);
}
}
int main(int argc, char **argv) {
int i, j, num_errors, symbols_layer;
cf_t *d[MAX_CODEWORDS], *x[MAX_LAYERS], *dp[MAX_CODEWORDS];
mimo_type_t type;
int nof_symb_cw[MAX_CODEWORDS];
int n[2];
parse_args(argc, argv);
if (lte_str2mimotype(mimo_type_name, &type)) {
fprintf(stderr, "Invalid MIMO type %s\n", mimo_type_name);
exit(-1);
}
if (nof_cw > 1) {
n[0] = nof_layers / nof_cw;
n[1] = nof_layers - n[0];
nof_symb_cw[0] = nof_symbols * n[0];
nof_symb_cw[1] = nof_symbols * n[1];
} else {
nof_symb_cw[0] = nof_symbols;
nof_symb_cw[1] = 0;
}
for (i=0;i<nof_cw;i++) {
d[i] = malloc(sizeof(cf_t) * nof_symb_cw[i]);
if (!d[i]) {
perror("malloc");
exit(-1);
}
dp[i] = malloc(sizeof(cf_t) * nof_symb_cw[i]);
if (!dp[i]) {
perror("malloc");
exit(-1);
}
}
for (i=0;i<nof_layers;i++) {
x[i] = malloc(sizeof(cf_t) * nof_symbols);
if (!x[i]) {
perror("malloc");
exit(-1);
}
}
/* generate random data */
for (i=0;i<nof_cw;i++) {
for (j=0;j<nof_symb_cw[i];j++) {
d[i][j] = 100 * (rand()/RAND_MAX + I*rand()/RAND_MAX);
}
}
/* layer encode */
if ((symbols_layer = layermap_type(d, x, nof_cw, nof_layers, nof_symb_cw, type)) < 0) {
fprintf(stderr, "Error layer mapper encoder\n");
exit(-1);
}
/* layer decode */
if (layerdemap_type(x, dp, nof_layers, nof_cw, nof_symbols/nof_layers, nof_symb_cw, type) < 0) {
fprintf(stderr, "Error layer mapper encoder\n");
exit(-1);
}
/* check errors */
num_errors = 0;
for (i=0;i<nof_cw;i++) {
for (j=0;j<nof_symb_cw[i];j++) {
if (d[i][j] != dp[i][j]) {
num_errors++;
}
}
}
for (i=0;i<nof_cw;i++) {
free(d[i]);
free(dp[i]);
}
for (i=0;i<nof_layers;i++) {
free(x[i]);
}
if (num_errors) {
printf("%d Errors\n", num_errors);
exit(-1);
} else {
printf("Ok\n");
exit(0);
}
}

@ -37,11 +37,11 @@ void demod_hard_init(demod_hard_t* q) {
bzero((void*) q, sizeof(demod_hard_t)); bzero((void*) q, sizeof(demod_hard_t));
} }
void demod_hard_table(demod_hard_t* q, enum modem_std table) { void demod_hard_table_set(demod_hard_t* q, enum modem_std table) {
q->table = table; q->table = table;
} }
int demod_hard_demodulate(demod_hard_t* q, const cf_t* symbols, char *bits, int nsymbols) { int demod_hard_demodulate(demod_hard_t* q, cf_t* symbols, char *bits, int nsymbols) {
int nbits=-1; int nbits=-1;
switch(q->table) { switch(q->table) {
@ -68,7 +68,7 @@ int demod_hard_demodulate(demod_hard_t* q, const cf_t* symbols, char *bits, int
int demod_hard_initialize(demod_hard_hl* hl) { int demod_hard_initialize(demod_hard_hl* hl) {
demod_hard_init(&hl->obj); demod_hard_init(&hl->obj);
demod_hard_table(&hl->obj,hl->init.std); demod_hard_table_set(&hl->obj,hl->init.std);
return 0; return 0;
} }

@ -0,0 +1,40 @@
#
# Copyright 2012-2013 The libLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the libLTE library.
#
# libLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# libLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
########################################################################
# MODEM TEST
########################################################################
ADD_EXECUTABLE(modem_test modem_test.c)
TARGET_LINK_LIBRARIES(modem_test lte)
ADD_TEST(modem_bpsk modem_test -n 1020 -m 1)
ADD_TEST(modem_qpsk modem_test -n 1020 -m 2)
ADD_TEST(modem_qam16 modem_test -n 1020 -m 4)
ADD_TEST(modem_qam64 modem_test -n 1020 -m 6)
ADD_TEST(modem_bpsk_soft modem_test -n 1020 -m 1 -s)
ADD_TEST(modem_qpsk_soft modem_test -n 1020 -m 2 -s)
ADD_TEST(modem_qam16_soft modem_test -n 1020 -m 4 -s)
ADD_TEST(modem_qam64_soft modem_test -n 1020 -m 6 -s)

@ -0,0 +1,184 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include "lte.h"
int num_bits = 1000;
enum modem_std modulation;
bool soft_output = false, soft_exact = false;
void usage(char *prog) {
printf("Usage: %s [nmse]\n", prog);
printf("\t-n num_bits [Default %d]\n", num_bits);
printf("\t-m modulation (1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64) [Default BPSK]\n");
printf("\t-s soft outputs [Default hard]\n");
printf("\t-e soft outputs exact algorithm [Default approx]\n");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "nmse")) != -1) {
switch (opt) {
case 'n':
num_bits = atoi(argv[optind]);
break;
case 's':
soft_output = true;
break;
case 'e':
soft_exact = true;
break;
case 'm':
switch(atoi(argv[optind])) {
case 1:
modulation = LTE_BPSK;
break;
case 2:
modulation = LTE_QPSK;
break;
case 4:
modulation = LTE_QAM16;
break;
case 6:
modulation = LTE_QAM64;
break;
default:
fprintf(stderr, "Invalid modulation %d. Possible values: "
"(1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64)\n", atoi(argv[optind]));
break;
}
break;
default:
usage(argv[0]);
exit(-1);
}
}
}
int main(int argc, char **argv) {
int i;
modem_table_t mod;
demod_hard_t demod_hard;
demod_soft_t demod_soft;
char *input, *output;
cf_t *symbols;
float *llr;
parse_args(argc, argv);
/* initialize objects */
if (modem_table_std(&mod, modulation, soft_output)) {
fprintf(stderr, "Error initializing modem table\n");
exit(-1);
}
/* check that num_bits is multiple of num_bits x symbol */
if (num_bits % mod.nbits_x_symbol) {
fprintf(stderr, "Error num_bits must be multiple of %d\n", mod.nbits_x_symbol);
exit(-1);
}
if (soft_output) {
demod_soft_init(&demod_soft);
demod_soft_table_set(&demod_soft, &mod);
demod_soft_alg_set(&demod_soft, soft_exact?EXACT:APPROX);
} else {
demod_hard_init(&demod_hard);
demod_hard_table_set(&demod_hard, modulation);
}
/* allocate buffers */
input = malloc(sizeof(char) * num_bits);
if (!input) {
perror("malloc");
exit(-1);
}
output = malloc(sizeof(char) * num_bits);
if (!output) {
perror("malloc");
exit(-1);
}
symbols = malloc(sizeof(cf_t) * num_bits / mod.nbits_x_symbol);
if (!symbols) {
perror("malloc");
exit(-1);
}
llr = malloc(sizeof(float) * num_bits);
if (!llr) {
perror("malloc");
exit(-1);
}
/* generate random data */
srand(time(NULL));
for (i=0;i<num_bits;i++) {
input[i] = rand()%2;
}
/* modulate */
mod_modulate(&mod, input, symbols, num_bits);
/* demodulate */
if (soft_output) {
demod_soft_demodulate(&demod_soft, symbols, llr, num_bits / mod.nbits_x_symbol);
for (i=0;i<num_bits;i++) {
output[i] = llr[i]>=0 ? 1 : 0;
}
} else {
demod_hard_demodulate(&demod_hard, symbols, output, num_bits / mod.nbits_x_symbol);
}
/* check errors */
for (i=0;i<num_bits;i++) {
if (input[i] != output[i]) {
fprintf(stderr, "Error in bit %d\n", i);
exit(-1);
}
}
free(llr);
free(symbols);
free(output);
free(input);
modem_table_free(&mod);
printf("Ok\n");
exit(0);
}

@ -404,17 +404,13 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS_CTRL], int no
/* Set pointers for layermapping & precoding */ /* Set pointers for layermapping & precoding */
int i; int i;
int nof_bits = 2 * q->nof_symbols; int nof_bits = 2 * q->nof_symbols;
cf_t *x[MAX_LAYERS];
cf_t *x[MAX_LAYERS], *d[MAX_CODEWORDS];
/* number of layers equals number of ports */ /* number of layers equals number of ports */
for (i=0;i<MAX_PORTS_CTRL;i++) { for (i=0;i<MAX_PORTS_CTRL;i++) {
x[i] = q->pbch_x[i]; x[i] = q->pbch_x[i];
} }
memset(&x[MAX_PORTS_CTRL], 0, sizeof(cf_t*) * (MAX_LAYERS - MAX_PORTS_CTRL)); memset(&x[MAX_PORTS_CTRL], 0, sizeof(cf_t*) * (MAX_LAYERS - MAX_PORTS_CTRL));
/* always one codeword only */
d[0] = q->pbch_d;
memset(&d[1], 0, sizeof(cf_t*) * (MAX_CODEWORDS - 1));
/* extract symbols */ /* extract symbols */
if (q->nof_symbols != pbch_get(slot1_symbols, q->pbch_symbols[0], nof_prb, if (q->nof_symbols != pbch_get(slot1_symbols, q->pbch_symbols[0], nof_prb,
@ -441,8 +437,14 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS_CTRL], int no
INFO("Trying %d TX antennas with %d frames\n", nant, q->frame_idx); INFO("Trying %d TX antennas with %d frames\n", nant, q->frame_idx);
precoding_decode(q->pbch_symbols, q->ce, x, nant, q->nof_symbols, TX_DIVERSITY); /* in conctrol channels, only diversity is supported */
layermap_decode(x, d, nant, 1, q->nof_symbols/nant, TX_DIVERSITY); if (nant == 1) {
/* no need for layer demapping */
predecoding_single_zf(q->pbch_symbols[0], q->ce[0], q->pbch_d, q->nof_symbols);
} else {
predecoding_diversity_zf(q->pbch_symbols, q->ce, x, nant, q->nof_symbols);
layerdemap_diversity(x, q->pbch_d, nant, q->nof_symbols/nant);
}
/* demodulate symbols */ /* demodulate symbols */
demod_soft_sigma_set(&q->demod, ebno); demod_soft_sigma_set(&q->demod, ebno);
@ -482,9 +484,10 @@ void pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *slot1_symbols[MAX_PORTS_CTRL]
int i; int i;
int nof_bits = 2 * q->nof_symbols; int nof_bits = 2 * q->nof_symbols;
/* Set pointers for layermapping & precoding */
assert(nof_ports < MAX_PORTS_CTRL); assert(nof_ports < MAX_PORTS_CTRL);
cf_t *x[MAX_LAYERS], *d[MAX_CODEWORDS];
/* Set pointers for layermapping & precoding */
cf_t *x[MAX_LAYERS];
/* number of layers equals number of ports */ /* number of layers equals number of ports */
for (i=0;i<nof_ports;i++) { for (i=0;i<nof_ports;i++) {
@ -492,11 +495,6 @@ void pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *slot1_symbols[MAX_PORTS_CTRL]
} }
memset(&x[nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - nof_ports)); memset(&x[nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - nof_ports));
/* there's always 1 codeword only */
d[0] = q->pbch_d;
memset(&d[1], 0, sizeof(cf_t*) * (MAX_CODEWORDS - 1));
if (q->frame_idx == 0) { if (q->frame_idx == 0) {
/* pack MIB */ /* pack MIB */
pbch_mib_pack(mib, q->data); pbch_mib_pack(mib, q->data);
@ -517,8 +515,12 @@ void pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *slot1_symbols[MAX_PORTS_CTRL]
/* layer mapping & precoding */ /* layer mapping & precoding */
layermap_encode(d, x, nof_ports, 1, q->nof_symbols/nof_ports, TX_DIVERSITY); if (nof_ports > 1) {
precoding_encode(x, q->pbch_symbols, nof_ports, q->nof_symbols/nof_ports, TX_DIVERSITY); layermap_diversity(q->pbch_d, x, nof_ports, q->nof_symbols/nof_ports);
precoding_diversity(x, q->pbch_symbols, nof_ports, q->nof_symbols/nof_ports);
} else {
memcpy(q->pbch_symbols[0], q->pbch_d, q->nof_symbols * sizeof(cf_t));
}
/* mapping to resource elements */ /* mapping to resource elements */

@ -0,0 +1,33 @@
#
# Copyright 2012-2013 The libLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the libLTE library.
#
# libLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# libLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
########################################################################
# RATEMATCHING TEST
########################################################################
ADD_EXECUTABLE(rm_conv_test rm_conv_test.c)
TARGET_LINK_LIBRARIES(rm_conv_test lte)
ADD_TEST(rm_conv_test_1 rm_conv_test -t 480 -r 1920)
ADD_TEST(rm_conv_test_2 rm_conv_test -t 1920 -r 480)

@ -0,0 +1,134 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include "lte.h"
int nof_tx_bits=-1, nof_rx_bits=-1;
void usage(char *prog) {
printf("Usage: %s -t nof_tx_bits -r nof_rx_bits\n", prog);
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "tr")) != -1) {
switch (opt) {
case 't':
nof_tx_bits = atoi(argv[optind]);
break;
case 'r':
nof_rx_bits = atoi(argv[optind]);
break;
default:
usage(argv[0]);
exit(-1);
}
}
if (nof_tx_bits == -1) {
usage(argv[0]);
exit(-1);
}
if (nof_rx_bits == -1) {
usage(argv[0]);
exit(-1);
}
}
int main(int argc, char **argv) {
int i;
char *bits, *rm_bits;
float *rm_symbols, *unrm_symbols;
int nof_errors;
parse_args(argc, argv);
bits = malloc(sizeof(char) * nof_tx_bits);
if (!bits) {
perror("malloc");
exit(-1);
}
rm_bits = malloc(sizeof(char) * nof_rx_bits);
if (!rm_bits) {
perror("malloc");
exit(-1);
}
rm_symbols = malloc(sizeof(float) * nof_rx_bits);
if (!rm_symbols) {
perror("malloc");
exit(-1);
}
unrm_symbols = malloc(sizeof(float) * nof_tx_bits);
if (!unrm_symbols) {
perror("malloc");
exit(-1);
}
for (i=0;i<nof_tx_bits;i++) {
bits[i] = rand()%2;
}
if (rm_conv_tx(bits, rm_bits, nof_tx_bits, nof_rx_bits)) {
exit(-1);
}
for (i=0;i<nof_rx_bits;i++) {
rm_symbols[i] = rm_bits[i]?1:-1;
}
if (rm_conv_rx(rm_symbols, unrm_symbols, nof_rx_bits, nof_tx_bits)) {
exit(-1);
}
for (i=0;i<nof_tx_bits;i++) {
if ((unrm_symbols[i] > 0) != bits[i]) {
nof_errors++;
}
}
if (nof_rx_bits > nof_tx_bits) {
if (nof_errors) {
printf("nof_errors=%d\n", nof_errors);
exit(-1);
}
}
free(bits);
free(rm_bits);
free(rm_symbols);
free(unrm_symbols);
printf("Ok\n");
exit(0);
}

@ -0,0 +1,35 @@
#
# Copyright 2012-2013 The libLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the libLTE library.
#
# libLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# libLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
########################################################################
# SCRAMBLING TEST
########################################################################
ADD_EXECUTABLE(scrambling_test scrambling_test.c)
TARGET_LINK_LIBRARIES(scrambling_test lte)
ADD_TEST(scrambling_pbch_bit scrambling_test -s PBCH -c 50)
ADD_TEST(scrambling_pbch_float scrambling_test -s PBCH -c 50 -f)
ADD_TEST(scrambling_pbch_e_bit scrambling_test -s PBCH -c 50 -e)
ADD_TEST(scrambling_pbch_e_float scrambling_test -s PBCH -c 50 -f -e)

@ -0,0 +1,165 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include "lte.h"
char *sequence_name = NULL;
bool do_floats = false;
lte_cp_t cp = CPNORM;
int cell_id = -1;
void usage(char *prog) {
printf("Usage: %s [ef] -c cell_id -s [PBCH, PDSCH, PDCCH, PMCH, PUCCH]\n", prog);
printf("\t -e CP extended [Default CP Normal]\n");
printf("\t -f scramble floats [Default bits]\n");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "csef")) != -1) {
switch (opt) {
case 'c':
cell_id = atoi(argv[optind]);
break;
case 'e':
cp = CPEXT;
break;
case 'f':
do_floats = true;
break;
case 's':
sequence_name = argv[optind];
break;
default:
usage(argv[0]);
exit(-1);
}
}
if (cell_id == -1) {
usage(argv[0]);
exit(-1);
}
if (!sequence_name) {
usage(argv[0]);
exit(-1);
}
}
int init_sequence(sequence_t *seq, char *name) {
if (!strcmp(name, "PBCH")) {
return sequence_pbch(seq, cp, cell_id);
} else {
fprintf(stderr, "Unsupported sequence name %s\n", name);
return -1;
}
}
int main(int argc, char **argv) {
int i;
sequence_t seq;
char *input_b, *scrambled_b;
float *input_f, *scrambled_f;
parse_args(argc, argv);
if (init_sequence(&seq, sequence_name) == -1) {
fprintf(stderr, "Error initiating sequence %s\n", sequence_name);
exit(-1);
}
if (!do_floats) {
input_b = malloc(sizeof(char) * seq.len);
if (!input_b) {
perror("malloc");
exit(-1);
}
scrambled_b = malloc(sizeof(char) * seq.len);
if (!scrambled_b) {
perror("malloc");
exit(-1);
}
for (i=0;i<seq.len;i++) {
input_b[i] = rand()%2;
scrambled_b[i] = input_b[i];
}
scrambling_bit(&seq, scrambled_b);
scrambling_bit(&seq, scrambled_b);
for (i=0;i<seq.len;i++) {
if (scrambled_b[i] != input_b[i]) {
printf("Error in %d\n", i);
exit(-1);
}
}
free(input_b);
free(scrambled_b);
} else {
input_f = malloc(sizeof(float) * seq.len);
if (!input_f) {
perror("malloc");
exit(-1);
}
scrambled_f = malloc(sizeof(float) * seq.len);
if (!scrambled_f) {
perror("malloc");
exit(-1);
}
for (i=0;i<seq.len;i++) {
input_f[i] = 100*(rand()/RAND_MAX);
scrambled_f[i] = input_f[i];
}
scrambling_float(&seq, scrambled_f);
scrambling_float(&seq, scrambled_f);
for (i=0;i<seq.len;i++) {
if (scrambled_f[i] != input_f[i]) {
printf("Error in %d\n", i);
exit(-1);
}
}
free(input_f);
free(scrambled_f);
}
printf("Ok\n");
sequence_free(&seq);
exit(0);
}
Loading…
Cancel
Save