Added scrambling, ratematching and layer mapping tests
This commit is contained in:
parent
bea03bfdd2
commit
67b8cf3ee2
|
@ -42,6 +42,10 @@ INCLUDE(libLTEPackage) #setup cpack
|
|||
|
||||
include(CTest)
|
||||
set( CTEST_MEMORYCHECK_COMMAND valgrind )
|
||||
CONFIGURE_FILE(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
########################################################################
|
||||
# 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/.
|
||||
#
|
||||
|
||||
|
||||
#################################################################
|
||||
# TO BE MOVED TO UNIT TESTS
|
||||
# EXAMPLES
|
||||
#################################################################
|
||||
|
||||
add_executable(hl_example hl_example.c)
|
||||
|
@ -29,8 +30,13 @@ target_link_libraries(hl_example lte)
|
|||
add_executable(ll_example ll_example.c)
|
||||
target_link_libraries(ll_example lte)
|
||||
|
||||
add_executable(synch_test synch_test.c)
|
||||
target_link_libraries(synch_test lte)
|
||||
add_executable(synch_file synch_file.c)
|
||||
target_link_libraries(synch_file lte)
|
||||
|
||||
|
||||
#################################################################
|
||||
# TO BE MOVED TO UNIT TESTS
|
||||
#################################################################
|
||||
|
||||
add_executable(mib_test mib_test.c)
|
||||
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
|
||||
#################################################################
|
||||
|
||||
add_executable(mib_track mib_track.c)
|
||||
target_link_libraries(mib_track lte)
|
||||
add_executable(pbch_ue pbch_ue.c)
|
||||
target_link_libraries(pbch_ue lte)
|
||||
|
||||
add_executable(enodeb_bch enodeb_bch.c)
|
||||
target_link_libraries(enodeb_bch lte)
|
||||
add_executable(pbch_enodeb pbch_enodeb.c)
|
||||
target_link_libraries(pbch_enodeb lte)
|
||||
|
||||
IF(${CUHD_FIND} EQUAL -1)
|
||||
SET_TARGET_PROPERTIES(mib_track PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
|
||||
SET_TARGET_PROPERTIES(enodeb_bch PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
|
||||
SET_TARGET_PROPERTIES(pbch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
|
||||
SET_TARGET_PROPERTIES(pbch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
|
||||
ELSE(${CUHD_FIND} EQUAL -1)
|
||||
target_link_libraries(mib_track cuhd)
|
||||
target_link_libraries(enodeb_bch cuhd)
|
||||
target_link_libraries(pbch_ue cuhd)
|
||||
target_link_libraries(pbch_enodeb cuhd)
|
||||
ENDIF(${CUHD_FIND} EQUAL -1)
|
||||
|
||||
IF(${GRAPHICS_FIND} EQUAL -1)
|
||||
SET_TARGET_PROPERTIES(mib_track PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
|
||||
SET_TARGET_PROPERTIES(enodeb_bch PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
|
||||
SET_TARGET_PROPERTIES(pbch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
|
||||
SET_TARGET_PROPERTIES(pbch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
|
||||
ELSE(${GRAPHICS_FIND} EQUAL -1)
|
||||
target_link_libraries(mib_track graphics)
|
||||
target_link_libraries(enodeb_bch graphics)
|
||||
target_link_libraries(pbch_ue graphics)
|
||||
target_link_libraries(pbch_enodeb graphics)
|
||||
ENDIF(${GRAPHICS_FIND} EQUAL -1)
|
||||
|
||||
|
||||
|
@ -77,14 +83,14 @@ ENDIF(${GRAPHICS_FIND} EQUAL -1)
|
|||
|
||||
IF(${CUHD_FIND} GREATER -1)
|
||||
|
||||
add_executable(rssi_scan_usrp rssi_scan_usrp.c)
|
||||
target_link_libraries(rssi_scan_usrp lte cuhd )
|
||||
add_executable(scan_rssi scan_rssi.c)
|
||||
target_link_libraries(scan_rssi lte cuhd )
|
||||
|
||||
add_executable(pss_scan_usrp pss_scan_usrp.c)
|
||||
target_link_libraries(pss_scan_usrp lte cuhd )
|
||||
add_executable(scan_pss scan_pss.c)
|
||||
target_link_libraries(scan_pss lte cuhd )
|
||||
|
||||
add_executable(mib_scan_usrp mib_scan_usrp.c)
|
||||
target_link_libraries(mib_scan_usrp lte cuhd )
|
||||
add_executable(scan_mib scan_mib.c)
|
||||
target_link_libraries(scan_mib lte cuhd )
|
||||
|
||||
MESSAGE(STATUS " UHD examples will be installed.")
|
||||
|
||||
|
|
|
@ -37,20 +37,18 @@ char *input_file_name;
|
|||
char *output_file_name="abs_corr.txt";
|
||||
int nof_slots=100, frame_length=9600, symbol_sz=128;
|
||||
float corr_peak_threshold=25.0;
|
||||
int file_binary = 0;
|
||||
int out_N_id_2 = 0, force_N_id_2=-1;
|
||||
|
||||
#define CFO_AUTO -9999.0
|
||||
float force_cfo = CFO_AUTO;
|
||||
|
||||
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-l frame_length [Default %d]\n", frame_length);
|
||||
printf("\t-n number of frames [Default %d]\n", nof_slots);
|
||||
printf("\t-t correlation threshold [Default %g]\n", corr_peak_threshold);
|
||||
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-f force_N_id_2 [Default %d]\n", force_N_id_2);
|
||||
printf("\t-c force_cfo [Default disabled]\n");
|
||||
|
@ -58,7 +56,7 @@ void usage(char *prog) {
|
|||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "ionltsbNfc")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "ionltsNfc")) != -1) {
|
||||
switch(opt) {
|
||||
case 'i':
|
||||
input_file_name = argv[optind];
|
||||
|
@ -78,9 +76,6 @@ void parse_args(int argc, char **argv) {
|
|||
case 's':
|
||||
symbol_sz = atof(argv[optind]);
|
||||
break;
|
||||
case 'b':
|
||||
file_binary = 1;
|
||||
break;
|
||||
case 'N':
|
||||
out_N_id_2 = atoi(argv[optind]);
|
||||
break;
|
||||
|
@ -130,12 +125,11 @@ int main(int argc, char **argv) {
|
|||
gettimeofday(&tdata[1], NULL);
|
||||
printf("Initializing...");fflush(stdout);
|
||||
|
||||
data_type_t type = file_binary?COMPLEX_FLOAT_BIN:COMPLEX_FLOAT;
|
||||
if (filesource_init(&fsrc, input_file_name, type)) {
|
||||
if (filesource_init(&fsrc, input_file_name, COMPLEX_FLOAT_BIN)) {
|
||||
fprintf(stderr, "Error opening file %s\n", input_file_name);
|
||||
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);
|
||||
exit(-1);
|
||||
}
|
|
@ -34,8 +34,8 @@
|
|||
|
||||
#define MAX_PORTS 4
|
||||
#define MAX_PORTS_CTRL 4
|
||||
#define MAX_LAYERS 4
|
||||
#define MAX_CODEWORDS 4
|
||||
#define MAX_LAYERS 8
|
||||
#define MAX_CODEWORDS 2
|
||||
|
||||
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 {
|
||||
TX_DIVERSITY, SPATIAL_MULTIPLEX
|
||||
SINGLE_ANTENNA,TX_DIVERSITY, SPATIAL_MULTIPLEX
|
||||
} 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_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
|
||||
|
|
|
@ -31,14 +31,23 @@
|
|||
|
||||
typedef _Complex float cf_t;
|
||||
|
||||
/* Generates the vector of data symbols "d" based on the vector of layer-mapped symbols "x"
|
||||
*/
|
||||
void layermap_decode(cf_t *x[MAX_LAYERS], cf_t *d[MAX_CODEWORDS], int nof_layers, int nof_cw,
|
||||
int nof_layer_symbols, mimo_type_t type);
|
||||
|
||||
/* Generates the vector of layer-mapped symbols "x" based on the vector of data symbols "d"
|
||||
*/
|
||||
void layermap_encode(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_layers, int nof_cw,
|
||||
int nof_symbols, mimo_type_t type);
|
||||
int layermap_single(cf_t *d, cf_t *x, int nof_symbols);
|
||||
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 data symbols "d" based on the vector of layer-mapped symbols "x"
|
||||
*/
|
||||
int layerdemap_single(cf_t *x, cf_t *d, int nof_symbols);
|
||||
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
|
||||
|
|
|
@ -36,15 +36,21 @@ typedef _Complex float cf_t;
|
|||
* 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"
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
/* 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_ */
|
||||
|
|
|
@ -42,8 +42,8 @@ typedef struct {
|
|||
|
||||
|
||||
void demod_hard_init(demod_hard_t* q);
|
||||
void demod_hard_table(demod_hard_t* q, enum modem_std table);
|
||||
int demod_hard_demodulate(demod_hard_t* q, const cf_t* symbols, char *bits, int nsymbols);
|
||||
void demod_hard_table_set(demod_hard_t* q, enum modem_std table);
|
||||
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)
|
||||
|
||||
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) {
|
||||
dft_plan_free(&q->fft_plan);
|
||||
if (q->tmp) {
|
||||
free(q->tmp);
|
||||
}
|
||||
bzero(q, sizeof(lte_fft_t));
|
||||
}
|
||||
|
||||
|
|
|
@ -134,6 +134,30 @@ struct lte_band lte_bands[NOF_LTE_BANDS] = {
|
|||
};
|
||||
#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) {
|
||||
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/sequence.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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/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 nof_layer_symbols, mimo_type_t type) {
|
||||
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) {
|
||||
|
||||
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) {
|
||||
case TX_DIVERSITY:
|
||||
for (i=0;i<nof_layer_symbols;i++) {
|
||||
d[0][2*i] = x[0][i];
|
||||
d[0][2*i+1] = x[1][i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Error: Unsupported transmit mode\n");
|
||||
switch(type) {
|
||||
case SINGLE_ANTENNA:
|
||||
if (nof_cw == 1 && nof_layers == 1) {
|
||||
return layermap_single(x[0], d[0], nof_symbols[0]);
|
||||
} else {
|
||||
fprintf(stderr, "Number of codewords and layers must be 1 for transmission on single antenna ports\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Error: Unsupported nof_ports=%d\n", nof_layers);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates the vector of layer-mapped symbols "x" based on the vector of data symbols "d"
|
||||
*/
|
||||
void layermap_encode(cf_t *d[MAX_CODEWORDS], cf_t *x[MAX_LAYERS], int nof_layers, int nof_cw,
|
||||
int nof_symbols, mimo_type_t type) {
|
||||
switch(nof_layers) {
|
||||
case 1:
|
||||
memcpy(x[0], d[0], nof_symbols * sizeof(cf_t));
|
||||
case TX_DIVERSITY:
|
||||
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;
|
||||
case SPATIAL_MULTIPLEX:
|
||||
return layermap_multiplex(d, x, nof_cw, nof_layers, nof_symbols);
|
||||
break;
|
||||
default:
|
||||
printf("Error: Unsupported nof_ports=%d\n", nof_layers);
|
||||
return;
|
||||
}
|
||||
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 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
|
||||
*/
|
||||
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) {
|
||||
|
||||
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(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,56 +31,141 @@
|
|||
#include <assert.h>
|
||||
#include <complex.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "lte/common/base.h"
|
||||
#include "lte/mimo/precoding.h"
|
||||
#include "lte/utils/vector.h"
|
||||
|
||||
/* 36.211 v10.3.0 Section 6.3.4 */
|
||||
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) {
|
||||
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 */
|
||||
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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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:
|
||||
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 */
|
||||
for (i=0;i<nof_symbols/2;i++) {
|
||||
h0 = ce[0][2*i];
|
||||
h1 = ce[1][2*i];
|
||||
hh = cabs(h0)*cabs(h0)+cabs(h1)*cabs(h1);
|
||||
r0 = y[0][2*i];
|
||||
r1 = y[0][2*i+1];
|
||||
x[0][i] = (conj(h0)*r0 + h1*conj(r1))/hh;
|
||||
x[1][i] = (h0*conj(r1) - h1*conj(r0))/hh;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
switch(nof_ports) {
|
||||
case 1:
|
||||
vec_div_ccc(y[0], ce[0], x[0], nof_symbols);
|
||||
break;
|
||||
case 2:
|
||||
switch(type) {
|
||||
case TX_DIVERSITY:
|
||||
/* FIXME: Use VOLK here */
|
||||
// 6.3.4.3
|
||||
for (i=0;i<nof_symbols/2;i++) {
|
||||
h0 = ce[0][2*i];
|
||||
h1 = ce[1][2*i];
|
||||
hh = cabs(h0)*cabs(h0)+cabs(h1)*cabs(h1);
|
||||
r0 = y[0][2*i];
|
||||
r1 = y[0][2*i+1];
|
||||
x[0][i] = (conj(h0)*r0 + h1*conj(r1))/hh;
|
||||
x[1][i] = (h0*conj(r1) - h1*conj(r0))/hh;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Error: Unsupported transmit mode\n");
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
switch(type) {
|
||||
case SINGLE_ANTENNA:
|
||||
if (nof_ports == 1 && nof_layers == 1) {
|
||||
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;
|
||||
default:
|
||||
printf("Error: Unsupported nof_ports=%d\n", nof_ports);
|
||||
return;
|
||||
case TX_DIVERSITY:
|
||||
if (nof_ports == nof_layers) {
|
||||
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;
|
||||
}
|
||||
|
||||
void precoding_encode(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_ports, int nof_symbols,
|
||||
mimo_type_t type) {
|
||||
switch(nof_ports) {
|
||||
case 1:
|
||||
memcpy(y[0], x[0], nof_symbols * sizeof(cf_t));
|
||||
break;
|
||||
default:
|
||||
printf("Error: Unsupported nof_ports=%d\n", nof_ports);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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) {
|
||||
demod_hard_init(&hl->obj);
|
||||
demod_hard_table(&hl->obj,hl->init.std);
|
||||
demod_hard_table_set(&hl->obj,hl->init.std);
|
||||
|
||||
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 */
|
||||
int i;
|
||||
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 */
|
||||
for (i=0;i<MAX_PORTS_CTRL;i++) {
|
||||
x[i] = q->pbch_x[i];
|
||||
}
|
||||
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 */
|
||||
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);
|
||||
|
||||
precoding_decode(q->pbch_symbols, q->ce, x, nant, q->nof_symbols, TX_DIVERSITY);
|
||||
layermap_decode(x, d, nant, 1, q->nof_symbols/nant, TX_DIVERSITY);
|
||||
/* in conctrol channels, only diversity is supported */
|
||||
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 */
|
||||
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 nof_bits = 2 * q->nof_symbols;
|
||||
|
||||
/* Set pointers for layermapping & precoding */
|
||||
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 */
|
||||
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));
|
||||
|
||||
/* 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) {
|
||||
/* pack MIB */
|
||||
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 */
|
||||
layermap_encode(d, x, nof_ports, 1, q->nof_symbols/nof_ports, TX_DIVERSITY);
|
||||
precoding_encode(x, q->pbch_symbols, nof_ports, q->nof_symbols/nof_ports, TX_DIVERSITY);
|
||||
if (nof_ports > 1) {
|
||||
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 */
|
||||
|
|
|
@ -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…
Reference in New Issue