mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'next' into next_testers
This commit is contained in:
commit
a7cd65e307
|
@ -1,6 +1,11 @@
|
|||
Change Log for Releases
|
||||
==============================
|
||||
|
||||
## 17.09
|
||||
* Added MIMO 2x2 in the PHY layer and srsUE (i.e. TM3/TM4)
|
||||
* eMBMS support in the PHY layer
|
||||
* Many bug-fixes and improved stability and performance in srsUE/srsENB
|
||||
|
||||
## 002.000.000
|
||||
* Added fully functional srsENB to srsLTE code
|
||||
* Merged srsUE code into srsLTE and reestructured PHY code
|
||||
|
|
|
@ -120,7 +120,7 @@ else(POLARSSL_FOUND)
|
|||
endif(BUILD_STATIC)
|
||||
add_definitions(-DHAVE_MBEDTLS)
|
||||
else(MBEDTLS_FOUND)
|
||||
message(FATAL_ERROR "Either polarssl or mbedtls is required to compile srsLTE")
|
||||
message(FATAL_ERROR "Either PolarSSL or mbedTLS are required to build srsLTE")
|
||||
endif (MBEDTLS_FOUND)
|
||||
endif(POLARSSL_FOUND)
|
||||
|
||||
|
|
15
README.md
15
README.md
|
@ -15,12 +15,13 @@ srsLTE is released under the AGPLv3 license and uses software from the OpenLTE p
|
|||
Common Features
|
||||
---------------
|
||||
|
||||
* LTE Release 8 compliant
|
||||
* LTE Release 8 compliant (with selected features of Release 9)
|
||||
* FDD configuration
|
||||
* Tested bandwidths: 1.4, 3, 5, 10, 15 and 20 MHz
|
||||
* Transmission mode 1 (single antenna) and 2 (transmit diversity)
|
||||
* Transmission mode 1 (single antenna), 2 (transmit diversity), 3 (CCD) and 4 (closed-loop spatial multiplexing)
|
||||
* Frequency-based ZF and MMSE equalizer
|
||||
* Highly optimized Turbo Decoder available in Intel SSE4.1/AVX (+100 Mbps) and standard C (+25 Mbps)
|
||||
* Evolved multimedia broadcast and multicast service (eMBMS)
|
||||
* Highly optimized Turbo Decoder available in Intel SSE4.1/AVX2 (+100 Mbps) and standard C (+25 Mbps)
|
||||
* MAC, RLC, PDCP, RRC, NAS, S1AP and GW layers
|
||||
* Detailed log system with per-layer log levels and hex dumps
|
||||
* MAC layer wireshark packet capture
|
||||
|
@ -33,6 +34,7 @@ srsUE Features
|
|||
* Cell search and synchronization procedure for the UE
|
||||
* Soft USIM supporting Milenage and XOR authentication
|
||||
* Virtual network interface *tun_srsue* created upon network attach
|
||||
* +100 Mbps DL in 20 MHz MIMO TM4 configuration in i7 Quad-Core CPU.
|
||||
* 75 Mbps DL in 20 MHz SISO configuration in i7 Quad-Core CPU.
|
||||
* 36 Mbps DL in 10 MHz SISO configuration in i5 Dual-Core CPU.
|
||||
|
||||
|
@ -55,6 +57,8 @@ srsENB has been tested and validated with the following handsets:
|
|||
* LG Nexus 5
|
||||
* LG Nexus 4
|
||||
* Motorola Moto G4 plus
|
||||
* Huawei P9/P9lite
|
||||
* Huawei dongles: E3276 and E398
|
||||
|
||||
Hardware
|
||||
--------
|
||||
|
@ -65,13 +69,14 @@ We have tested the following hardware:
|
|||
* USRP B210
|
||||
* USRP X300
|
||||
* bladeRF
|
||||
* limeSDR
|
||||
* limeSDR (currently, only the PHY-layer examples, i.e., pdsch_enodeb/ue are supported)
|
||||
|
||||
Build Instructions
|
||||
------------------
|
||||
|
||||
* Mandatory requirements:
|
||||
* Common:
|
||||
* cmake https://cmake.org/
|
||||
* libfftw http://www.fftw.org/
|
||||
* PolarSSL/mbedTLS https://tls.mbed.org
|
||||
* srsUE:
|
||||
|
@ -83,7 +88,7 @@ Build Instructions
|
|||
|
||||
For example, on Ubuntu 17.04, one can install the required libraries with:
|
||||
```
|
||||
sudo apt-get install libfftw3-dev libmbedtls-dev libboost-all-dev libconfig++-dev libsctp-dev
|
||||
sudo apt-get install cmake libfftw3-dev libmbedtls-dev libboost-all-dev libconfig++-dev libsctp-dev
|
||||
```
|
||||
Note that depending on your flavor and version of Linux, the actual package names may be different.
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ FIND_LIBRARY(
|
|||
HINTS $ENV{UHD_DIR}/lib
|
||||
PATHS /usr/local/lib
|
||||
/usr/lib
|
||||
/usr/lib/x86_64-linux-gnu
|
||||
/usr/local/lib64
|
||||
/usr/local/lib32
|
||||
)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
# and at http://www.gnu.org/licenses/.
|
||||
#
|
||||
|
||||
SET(SRSLTE_VERSION_MAJOR 002)
|
||||
SET(SRSLTE_VERSION_MINOR 000)
|
||||
SET(SRSLTE_VERSION_PATCH 000)
|
||||
SET(SRSLTE_VERSION_MAJOR 17)
|
||||
SET(SRSLTE_VERSION_MINOR 9)
|
||||
SET(SRSLTE_VERSION_PATCH 0)
|
||||
SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}")
|
||||
|
|
|
@ -241,19 +241,31 @@ int main(int argc, char **argv) {
|
|||
srslte_rf_stop_rx_stream(&rf);
|
||||
srslte_rf_flush_buffer(&rf);
|
||||
|
||||
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
|
||||
if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
return -1;
|
||||
}
|
||||
if (srslte_ue_dl_init(&ue_dl, cell, 1)) {
|
||||
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
return -1;
|
||||
}
|
||||
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
|
||||
fprintf(stderr, "Error initiating UE downlink processing module\n");
|
||||
return -1;
|
||||
}
|
||||
if (srslte_ue_mib_init(&ue_mib, cell)) {
|
||||
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
|
||||
fprintf(stderr, "Error initiating UE downlink processing module\n");
|
||||
return -1;
|
||||
}
|
||||
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initaiting UE MIB decoder\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
|
||||
fprintf(stderr, "Error initaiting UE MIB decoder\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
|
||||
srslte_ue_dl_set_rnti(&ue_dl, SRSLTE_SIRNTI);
|
||||
|
||||
|
@ -264,11 +276,15 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, "Error initiating FFT\n");
|
||||
return -1;
|
||||
}
|
||||
if (srslte_chest_dl_init(&chest, cell)) {
|
||||
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating channel estimator\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (srslte_chest_dl_set_cell(&chest, cell)) {
|
||||
fprintf(stderr, "Error initiating channel estimator\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
|
||||
|
||||
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
|
||||
|
@ -319,10 +335,9 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
|
||||
return -1;
|
||||
} else if (n == 0) {
|
||||
printf("CFO: %+6.4f kHz, SFO: %+6.4f kHz, NOI: %.2f, PDCCH-Det: %.3f\r",
|
||||
printf("CFO: %+6.4f kHz, SFO: %+6.4f kHz, PDCCH-Det: %.3f\r",
|
||||
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
|
||||
srslte_pdsch_average_noi(&ue_dl.pdsch),
|
||||
(float) ue_dl.nof_detected/nof_trials);
|
||||
(float) ue_dl.nof_detected/nof_trials);
|
||||
nof_trials++;
|
||||
} else {
|
||||
printf("Decoded SIB1. Payload: ");
|
||||
|
|
|
@ -188,6 +188,18 @@ int main(int argc, char **argv) {
|
|||
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
|
||||
signal(SIGINT, sig_int_handler);
|
||||
|
||||
if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
|
||||
fprintf(stderr, "Error initiating UE cell detect\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (cell_detect_config.max_frames_pss) {
|
||||
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
|
||||
}
|
||||
if (cell_detect_config.init_agc) {
|
||||
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
|
||||
}
|
||||
|
||||
for (freq=0;freq<nof_freqs && !go_exit;freq++) {
|
||||
|
||||
/* set rf_freq */
|
||||
|
@ -203,18 +215,6 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
|
||||
|
||||
if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
|
||||
fprintf(stderr, "Error initiating UE cell detect\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (cell_detect_config.max_frames_pss) {
|
||||
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
|
||||
}
|
||||
if (cell_detect_config.init_agc) {
|
||||
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
|
||||
}
|
||||
|
||||
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
|
||||
srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
|
||||
|
@ -222,7 +222,6 @@ int main(int argc, char **argv) {
|
|||
srslte_rf_start_rx_stream(&rf);
|
||||
|
||||
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
|
||||
srslte_ue_cellsearch_free(&cs);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error searching cell\n");
|
||||
exit(-1);
|
||||
|
@ -254,7 +253,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("\n\nFound %d cells\n", n_found_cells);
|
||||
for (int i=0;i<n_found_cells;i++) {
|
||||
printf("Found CELL %.1f MHz, EARFCN=%d, PHYID=%d, %d PRB, %d ports, PSS power=%.1f dBm\n",
|
||||
|
@ -268,7 +267,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
printf("\nBye\n");
|
||||
|
||||
|
||||
srslte_ue_cellsearch_free(&cs);
|
||||
srslte_rf_close(&rf);
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
|
@ -38,10 +40,11 @@
|
|||
|
||||
|
||||
#define UE_CRNTI 0x1234
|
||||
|
||||
#define M_CRNTI 0xFFFD
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
#include "srslte/phy/rf/rf.h"
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
srslte_rf_t rf;
|
||||
#else
|
||||
#warning Compiling pdsch_ue with no RF support
|
||||
|
@ -55,52 +58,67 @@ char *output_file_name = NULL;
|
|||
#define DOWN_KEY 66
|
||||
|
||||
srslte_cell_t cell = {
|
||||
25, // nof_prb
|
||||
1, // nof_ports
|
||||
0, // cell_id
|
||||
SRSLTE_CP_NORM, // cyclic prefix
|
||||
SRSLTE_PHICH_NORM, // PHICH length
|
||||
SRSLTE_PHICH_R_1 // PHICH resources
|
||||
25, // nof_prb
|
||||
1, // nof_ports
|
||||
0, // cell_id
|
||||
SRSLTE_CP_NORM, // cyclic prefix
|
||||
SRSLTE_PHICH_NORM, // PHICH length
|
||||
SRSLTE_PHICH_R_1 // PHICH resources
|
||||
};
|
||||
|
||||
uint16_t c = -1;
|
||||
|
||||
int net_port = -1; // -1 generates random dataThat means there is some problem sending samples to the device
|
||||
|
||||
uint32_t cfi = 1;
|
||||
uint32_t cfi = 2;
|
||||
uint32_t mcs_idx = 1, last_mcs_idx = 1;
|
||||
int nof_frames = -1;
|
||||
|
||||
|
||||
char mimo_type_str[32] = "single";
|
||||
uint32_t nof_tb = 1;
|
||||
uint32_t multiplex_pmi = 0;
|
||||
uint32_t multiplex_nof_layers = 1;
|
||||
|
||||
int mbsfn_area_id = -1;
|
||||
char *rf_args = "";
|
||||
float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
|
||||
|
||||
bool null_file_sink=false;
|
||||
srslte_filesink_t fsink;
|
||||
srslte_ofdm_t ifft;
|
||||
srslte_ofdm_t ifft_mbsfn;
|
||||
srslte_pbch_t pbch;
|
||||
srslte_pcfich_t pcfich;
|
||||
srslte_pdcch_t pdcch;
|
||||
srslte_pdsch_t pdsch;
|
||||
srslte_pdsch_cfg_t pdsch_cfg;
|
||||
srslte_pdsch_cfg_t pdsch_cfg;
|
||||
srslte_pmch_t pmch;
|
||||
srslte_pdsch_cfg_t pmch_cfg;
|
||||
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
|
||||
srslte_regs_t regs;
|
||||
srslte_ra_dl_dci_t ra_dl;
|
||||
srslte_ra_dl_dci_t ra_dl;
|
||||
int rvidx[SRSLTE_MAX_CODEWORDS] = {0, 0};
|
||||
|
||||
cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL}, *output_buffer [SRSLTE_MAX_PORTS] = {NULL};
|
||||
|
||||
|
||||
int sf_n_re, sf_n_samples;
|
||||
|
||||
pthread_t net_thread;
|
||||
pthread_t net_thread;
|
||||
void *net_thread_fnc(void *arg);
|
||||
sem_t net_sem;
|
||||
bool net_packet_ready = false;
|
||||
srslte_netsource_t net_source;
|
||||
srslte_netsink_t net_sink;
|
||||
|
||||
|
||||
int prbset_num = 1, last_prbset_num = 1;
|
||||
int prbset_orig = 0;
|
||||
//#define DATA_BUFF_SZ 1024*128
|
||||
//uint8_t data[8*DATA_BUFF_SZ], data2[DATA_BUFF_SZ];
|
||||
//uint8_t data_tmp[DATA_BUFF_SZ];
|
||||
|
||||
|
||||
#define DATA_BUFF_SZ 1024*1024
|
||||
uint8_t *data[2], data2[DATA_BUFF_SZ];
|
||||
|
@ -121,6 +139,7 @@ void usage(char *prog) {
|
|||
printf("\t-n number of frames [Default %d]\n", nof_frames);
|
||||
printf("\t-c cell id [Default %d]\n", cell.id);
|
||||
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
|
||||
printf("\t-M MBSFN area id [Default %d]\n", mbsfn_area_id);
|
||||
printf("\t-x Transmission mode[single|diversity|cdd|multiplex] [Default %s]\n", mimo_type_str);
|
||||
printf("\t-b Precoding Matrix Index (multiplex mode only)* [Default %d]\n", multiplex_pmi);
|
||||
printf("\t-w Number of codewords/layers (multiplex mode only)* [Default %d]\n", multiplex_nof_layers);
|
||||
|
@ -132,7 +151,8 @@ void usage(char *prog) {
|
|||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "aglfmoncpvutxbw")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "aglfmoncpvutxbwM")) != -1) {
|
||||
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
rf_args = argv[optind];
|
||||
|
@ -173,6 +193,9 @@ void parse_args(int argc, char **argv) {
|
|||
case 'w':
|
||||
multiplex_nof_layers = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'M':
|
||||
mbsfn_area_id = atoi(argv[optind]);
|
||||
break;
|
||||
case 'v':
|
||||
srslte_verbose++;
|
||||
break;
|
||||
|
@ -188,7 +211,7 @@ void parse_args(int argc, char **argv) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void base_init() {
|
||||
int i;
|
||||
|
||||
|
@ -245,6 +268,7 @@ void base_init() {
|
|||
bzero(output_buffer[i], sizeof(cf_t) * sf_n_samples);
|
||||
}
|
||||
|
||||
|
||||
/* open file or USRP */
|
||||
if (output_file_name) {
|
||||
if (strcmp(output_file_name, "NULL")) {
|
||||
|
@ -291,18 +315,36 @@ void base_init() {
|
|||
fprintf(stderr, "Error creating iFFT object\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error creating iFFT object\n");
|
||||
exit(-1);
|
||||
}
|
||||
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, 2);
|
||||
srslte_ofdm_set_normalize(&ifft_mbsfn, true);
|
||||
srslte_ofdm_set_normalize(&ifft, true);
|
||||
if (srslte_pbch_init(&pbch, cell)) {
|
||||
|
||||
|
||||
if (srslte_pbch_init(&pbch)) {
|
||||
fprintf(stderr, "Error creating PBCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (srslte_pbch_set_cell(&pbch, cell)) {
|
||||
fprintf(stderr, "Error creating PBCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (srslte_regs_init(®s, cell)) {
|
||||
fprintf(stderr, "Error initiating regs\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (srslte_pcfich_init(&pcfich, ®s, cell)) {
|
||||
if (srslte_pcfich_init(&pcfich, 1)) {
|
||||
fprintf(stderr, "Error creating PBCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (srslte_pcfich_set_cell(&pcfich, ®s, cell)) {
|
||||
fprintf(stderr, "Error creating PBCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -312,19 +354,34 @@ void base_init() {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
if (srslte_pdcch_init_tx(&pdcch, ®s, cell)) {
|
||||
if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error creating PDCCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (srslte_pdcch_set_cell(&pdcch, ®s, cell)) {
|
||||
fprintf(stderr, "Error creating PDCCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
bzero(&pdsch, sizeof(srslte_pdsch_t));
|
||||
if (srslte_pdsch_init_tx(&pdsch, cell)) {
|
||||
if (srslte_pdsch_init_enb(&pdsch, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (srslte_pdsch_set_cell(&pdsch, cell)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
srslte_pdsch_set_rnti(&pdsch, UE_CRNTI);
|
||||
|
||||
|
||||
if(mbsfn_area_id > -1){
|
||||
if (srslte_pmch_init(&pmch, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error creating PMCH object\n");
|
||||
}
|
||||
srslte_pmch_set_area_id(&pmch, mbsfn_area_id);
|
||||
}
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
softbuffers[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1);
|
||||
if (!softbuffers[i]) {
|
||||
|
@ -339,6 +396,7 @@ void base_init() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void base_free() {
|
||||
int i;
|
||||
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
|
@ -351,8 +409,12 @@ void base_free() {
|
|||
srslte_pdcch_free(&pdcch);
|
||||
srslte_regs_free(®s);
|
||||
srslte_pbch_free(&pbch);
|
||||
|
||||
if(mbsfn_area_id > -1){
|
||||
srslte_pmch_free(&pmch);
|
||||
}
|
||||
srslte_ofdm_tx_free(&ifft_mbsfn);
|
||||
srslte_ofdm_tx_free(&ifft);
|
||||
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
if (data[i]) {
|
||||
|
@ -466,7 +528,7 @@ int update_radl() {
|
|||
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &dummy_grant);
|
||||
srslte_ra_dl_grant_to_nbits(&dummy_grant, cfi, cell, 0, &dummy_nbits);
|
||||
srslte_ra_dl_grant_fprint(stdout, &dummy_grant);
|
||||
|
||||
dummy_grant.sf_type = SRSLTE_SF_NORM;
|
||||
if (pdsch_cfg.mimo_type != SRSLTE_MIMO_TYPE_SINGLE_ANTENNA) {
|
||||
printf("\nTransmission mode key table:\n");
|
||||
printf(" Mode | 1TB | 2TB |\n");
|
||||
|
@ -581,6 +643,7 @@ int update_control() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/** Function run in a separate thread to receive UDP data */
|
||||
void *net_thread_fnc(void *arg) {
|
||||
int n;
|
||||
|
@ -618,6 +681,7 @@ void *net_thread_fnc(void *arg) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int nf=0, sf_idx=0, N_id_2=0;
|
||||
cf_t pss_signal[SRSLTE_PSS_LEN];
|
||||
|
@ -630,7 +694,8 @@ int main(int argc, char **argv) {
|
|||
srslte_dci_msg_t dci_msg;
|
||||
srslte_dci_location_t locations[SRSLTE_NSUBFRAMES_X_FRAME][30];
|
||||
uint32_t sfn;
|
||||
srslte_chest_dl_t est;
|
||||
srslte_refsignal_t csr_refs;
|
||||
srslte_refsignal_t mbsfn_refs;
|
||||
|
||||
#ifdef DISABLE_RF
|
||||
if (argc < 3) {
|
||||
|
@ -659,17 +724,31 @@ int main(int argc, char **argv) {
|
|||
srslte_pss_generate(pss_signal, N_id_2);
|
||||
srslte_sss_generate(sss_signal0, sss_signal5, cell.id);
|
||||
|
||||
/* Generate CRS signals */
|
||||
if (srslte_chest_dl_init(&est, cell)) {
|
||||
|
||||
/* Generate reference signals */
|
||||
if(srslte_refsignal_cs_init(&csr_refs, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(mbsfn_area_id > -1) {
|
||||
if(srslte_refsignal_mbsfn_init(&mbsfn_refs, cell, mbsfn_area_id)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if(srslte_refsignal_cs_set_cell(&csr_refs, cell)){
|
||||
fprintf(stderr, "Error setting cell\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
sf_symbols[i] = sf_buffer[i%cell.nof_ports];
|
||||
slot1_symbols[i] = &sf_buffer[i%cell.nof_ports][SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)];
|
||||
}
|
||||
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
|
||||
|
||||
|
@ -718,48 +797,51 @@ int main(int argc, char **argv) {
|
|||
/* Initiate valid DCI locations */
|
||||
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
|
||||
srslte_pdcch_ue_locations(&pdcch, locations[i], 30, i, cfi, UE_CRNTI);
|
||||
|
||||
}
|
||||
|
||||
nf = 0;
|
||||
|
||||
bool send_data = false;
|
||||
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
srslte_softbuffer_tx_reset(softbuffers[i]);
|
||||
}
|
||||
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
bool start_of_burst = true;
|
||||
#endif
|
||||
|
||||
|
||||
while ((nf < nof_frames || nof_frames == -1) && !go_exit) {
|
||||
for (sf_idx = 0; sf_idx < SRSLTE_NSUBFRAMES_X_FRAME && (nf < nof_frames || nof_frames == -1); sf_idx++) {
|
||||
/* Set Antenna port resource elements to zero */
|
||||
bzero(sf_symbols[0], sizeof(cf_t) * sf_n_re);
|
||||
|
||||
/* Populate Synchronization signals if required */
|
||||
|
||||
if (sf_idx == 0 || sf_idx == 5) {
|
||||
srslte_pss_put_slot(pss_signal, sf_symbols[0], cell.nof_prb, SRSLTE_CP_NORM);
|
||||
srslte_sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_symbols[0], cell.nof_prb,
|
||||
SRSLTE_CP_NORM);
|
||||
}
|
||||
|
||||
|
||||
/* Copy zeros, SSS, PSS into the rest of antenna ports */
|
||||
for (i = 1; i < cell.nof_ports; i++) {
|
||||
memcpy(sf_symbols[i], sf_symbols[0], sizeof(cf_t) * sf_n_re);
|
||||
}
|
||||
|
||||
/* Put reference signals */
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_refsignal_cs_put_sf(cell, (uint32_t) i, est.csr_signal.pilots[i / 2][sf_idx], sf_symbols[i]);
|
||||
|
||||
if(sf_idx == 1 && mbsfn_area_id > -1){
|
||||
srslte_refsignal_mbsfn_put_sf(cell, 0,csr_refs.pilots[0][sf_idx], mbsfn_refs.pilots[0][sf_idx], sf_symbols[0]);
|
||||
} else {
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_refsignal_cs_put_sf(cell, (uint32_t) i, csr_refs.pilots[i / 2][sf_idx], sf_symbols[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
srslte_pbch_mib_pack(&cell, sfn, bch_payload);
|
||||
if (sf_idx == 0) {
|
||||
srslte_pbch_encode(&pbch, bch_payload, slot1_symbols, nf%4);
|
||||
}
|
||||
|
||||
srslte_pcfich_encode(&pcfich, cfi, sf_symbols, sf_idx);
|
||||
srslte_pcfich_encode(&pcfich, cfi, sf_symbols, sf_idx);
|
||||
|
||||
/* Update DL resource allocation from control port */
|
||||
if (update_control(sf_idx)) {
|
||||
|
@ -774,9 +856,11 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
} else {
|
||||
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs);
|
||||
for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) {
|
||||
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
|
||||
data[tb][i] = (uint8_t) rand();
|
||||
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||
if (pdsch_cfg.grant.tb_en[tb]) {
|
||||
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
|
||||
data[tb][i] = (uint8_t) rand();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Uncomment this to transmit on sf 0 and 5 only */
|
||||
|
@ -785,84 +869,134 @@ int main(int argc, char **argv) {
|
|||
} else {
|
||||
send_data = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (send_data) {
|
||||
srslte_dci_format_t dci_format;
|
||||
switch(pdsch_cfg.mimo_type) {
|
||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||
dci_format = SRSLTE_DCI_FORMAT1;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
case SRSLTE_MIMO_TYPE_CDD:
|
||||
dci_format = SRSLTE_DCI_FORMAT2A;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
|
||||
dci_format = SRSLTE_DCI_FORMAT2;
|
||||
if (multiplex_nof_layers == 1) {
|
||||
ra_dl.pinfo = (uint8_t) (multiplex_pmi + 1);
|
||||
} else {
|
||||
ra_dl.pinfo = (uint8_t) multiplex_pmi;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Wrong MIMO configuration\n");
|
||||
exit(SRSLTE_ERROR);
|
||||
}
|
||||
/* Encode PDCCH */
|
||||
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
|
||||
srslte_dci_msg_pack_pdsch(&ra_dl, dci_format, &dci_msg, cell.nof_prb, cell.nof_ports, false);
|
||||
if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], UE_CRNTI, sf_symbols, sf_idx, cfi)) {
|
||||
fprintf(stderr, "Error encoding DCI message\n");
|
||||
exit(-1);
|
||||
}
|
||||
if(sf_idx != 1 || mbsfn_area_id < 0) { // PDCCH + PDSCH
|
||||
srslte_dci_format_t dci_format;
|
||||
switch(pdsch_cfg.mimo_type) {
|
||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||
dci_format = SRSLTE_DCI_FORMAT1;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
case SRSLTE_MIMO_TYPE_CDD:
|
||||
dci_format = SRSLTE_DCI_FORMAT2A;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
|
||||
dci_format = SRSLTE_DCI_FORMAT2;
|
||||
if (multiplex_nof_layers == 1) {
|
||||
ra_dl.pinfo = (uint8_t) (multiplex_pmi + 1);
|
||||
} else {
|
||||
ra_dl.pinfo = (uint8_t) multiplex_pmi;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Wrong MIMO configuration\n");
|
||||
exit(SRSLTE_ERROR);
|
||||
}
|
||||
/* Encode PDCCH */
|
||||
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
|
||||
srslte_dci_msg_pack_pdsch(&ra_dl, dci_format, &dci_msg, cell.nof_prb, cell.nof_ports, false);
|
||||
if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], UE_CRNTI, sf_symbols, sf_idx, cfi)) {
|
||||
fprintf(stderr, "Error encoding DCI message\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Configure pdsch_cfg parameters */
|
||||
srslte_ra_dl_grant_t grant;
|
||||
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &grant);
|
||||
if (srslte_pdsch_cfg_mimo(&pdsch_cfg, cell, &grant, cfi, sf_idx, rvidx, pdsch_cfg.mimo_type, multiplex_pmi)) {
|
||||
fprintf(stderr, "Error configuring PDSCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Encode PDSCH */
|
||||
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, softbuffers, data, UE_CRNTI, sf_symbols)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (net_port > 0 && net_packet_ready) {
|
||||
if (null_file_sink) {
|
||||
for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) {
|
||||
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs);
|
||||
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) {
|
||||
/* Configure pdsch_cfg parameters */
|
||||
srslte_ra_dl_grant_t grant;
|
||||
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &grant);
|
||||
if (srslte_pdsch_cfg_mimo(&pdsch_cfg, cell, &grant, cfi, sf_idx, rvidx, pdsch_cfg.mimo_type, multiplex_pmi)) {
|
||||
fprintf(stderr, "Error configuring PDSCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Encode PDSCH */
|
||||
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, softbuffers, data, UE_CRNTI, sf_symbols)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (net_port > 0 && net_packet_ready) {
|
||||
if (null_file_sink) {
|
||||
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs);
|
||||
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) {
|
||||
fprintf(stderr, "Error sending data through UDP socket\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
net_packet_ready = false;
|
||||
sem_post(&net_sem);
|
||||
}
|
||||
}else{ // We're sending MCH on subframe 1 - PDCCH + PMCH
|
||||
|
||||
/* Encode PDCCH */
|
||||
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
|
||||
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_msg, cell.nof_prb, cell.nof_ports, false);
|
||||
if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], M_CRNTI, sf_symbols, sf_idx, cfi)) {
|
||||
fprintf(stderr, "Error encoding DCI message\n");
|
||||
exit(-1);
|
||||
}
|
||||
/* Configure pmch_cfg parameters */
|
||||
srslte_ra_dl_grant_t grant;
|
||||
grant.nof_tb = 1;
|
||||
grant.mcs[0].idx = 2;
|
||||
grant.mcs[0].mod = SRSLTE_MOD_QPSK;
|
||||
grant.nof_prb = cell.nof_prb;
|
||||
grant.sf_type = SRSLTE_SF_MBSFN;
|
||||
grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod);
|
||||
srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb);
|
||||
for(int i = 0; i < 2; i++){
|
||||
for(int j = 0; j < grant.nof_prb; j++){
|
||||
grant.prb_idx[i][j] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, sf_idx)) {
|
||||
fprintf(stderr, "Error configuring PMCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
/* Encode PMCH */
|
||||
if (srslte_pmch_encode(&pmch, &pmch_cfg, softbuffers[0], data[0], mbsfn_area_id, sf_symbols)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (net_port > 0 && net_packet_ready) {
|
||||
if (null_file_sink) {
|
||||
srslte_bit_pack_vector(data[0], data_tmp, pmch_cfg.grant.mcs[0].tbs);
|
||||
if (srslte_netsink_write(&net_sink, data_tmp, 1+(pmch_cfg.grant.mcs[0].tbs-1)/8) < 0) {
|
||||
fprintf(stderr, "Error sending data through UDP socket\n");
|
||||
}
|
||||
}
|
||||
net_packet_ready = false;
|
||||
sem_post(&net_sem);
|
||||
}
|
||||
net_packet_ready = false;
|
||||
sem_post(&net_sem);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transform to OFDM symbols */
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_ofdm_tx_sf(&ifft, sf_buffer[i], output_buffer[i]);
|
||||
}
|
||||
|
||||
/* Transform to OFDM symbols */
|
||||
if(sf_idx != 1 || mbsfn_area_id < 0){
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_ofdm_tx_sf(&ifft, sf_buffer[i], output_buffer[i]);
|
||||
}
|
||||
}else{
|
||||
srslte_ofdm_tx_sf(&ifft_mbsfn, sf_buffer[0], output_buffer[0]);
|
||||
}
|
||||
|
||||
/* send to file or usrp */
|
||||
if (output_file_name) {
|
||||
if (!null_file_sink) {
|
||||
srslte_filesink_write_multi(&fsink, (void**) output_buffer, sf_n_samples, cell.nof_ports);
|
||||
srslte_filesink_write_multi(&fsink, (void**) output_buffer, sf_n_samples, cell.nof_ports);
|
||||
}
|
||||
usleep(1000);
|
||||
} else {
|
||||
#ifndef DISABLE_RF
|
||||
float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb);
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_vec_sc_prod_cfc(output_buffer[i], rf_amp * norm_factor, output_buffer[i], SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
}
|
||||
srslte_rf_send_multi(&rf, (void**) output_buffer, sf_n_samples, true, start_of_burst, false);
|
||||
start_of_burst=false;
|
||||
float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb);
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_vec_sc_prod_cfc(output_buffer[i], rf_amp * norm_factor, output_buffer[i], SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
}
|
||||
srslte_rf_send_multi(&rf, (void**) output_buffer, sf_n_samples, true, start_of_burst, false);
|
||||
start_of_burst=false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,10 +36,8 @@
|
|||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <srslte/srslte.h>
|
||||
#include <srslte/phy/phch/pdsch_cfg.h>
|
||||
#include <srslte/phy/phch/ra.h>
|
||||
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
#include "srslte/phy/io/filesink.h"
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
#define ENABLE_AGC_DEFAULT
|
||||
|
@ -69,7 +67,7 @@ sem_t plot_sem;
|
|||
uint32_t plot_sf_idx=0;
|
||||
bool plot_track = true;
|
||||
#endif
|
||||
|
||||
char *output_file_name;
|
||||
#define PRINT_CHANGE_SCHEDULIGN
|
||||
|
||||
//#define CORRECT_SAMPLE_OFFSET
|
||||
|
@ -101,6 +99,8 @@ typedef struct {
|
|||
int net_port_signal;
|
||||
char *net_address_signal;
|
||||
int decimate;
|
||||
int32_t mbsfn_area_id;
|
||||
uint8_t non_mbsfn_region;
|
||||
int verbose;
|
||||
}prog_args_t;
|
||||
|
||||
|
@ -132,10 +132,12 @@ void args_default(prog_args_t *args) {
|
|||
args->net_address_signal = "127.0.0.1";
|
||||
args->decimate = 0;
|
||||
args->cpu_affinity = -1;
|
||||
args->mbsfn_area_id = -1;
|
||||
args->non_mbsfn_region = 2;
|
||||
}
|
||||
|
||||
void usage(prog_args_t *args, char *prog) {
|
||||
printf("Usage: %s [agpPoOcildDnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
|
||||
printf("Usage: %s [agpPoOcildDnruMNv] -f rx_frequency (in Hz) | -i input_file\n", prog);
|
||||
#ifndef DISABLE_RF
|
||||
printf("\t-a RF args [Default %s]\n", args->rf_args);
|
||||
printf("\t-A Number of RX antennas [Default %d]\n", args->rf_nof_rx_ant);
|
||||
|
@ -169,13 +171,15 @@ void usage(prog_args_t *args, char *prog) {
|
|||
printf("\t-S remote UDP address to send input signal [Default %s]\n", args->net_address_signal);
|
||||
printf("\t-u remote TCP port to send data (-1 does nothing with it) [Default %d]\n", args->net_port);
|
||||
printf("\t-U remote TCP address to send data [Default %s]\n", args->net_address);
|
||||
printf("\t-M MBSFN area id [Default %d]\n", args->mbsfn_area_id);
|
||||
printf("\t-N Non-MBSFN region [Default %d]\n", args->non_mbsfn_region);
|
||||
printf("\t-v [set srslte_verbose to debug, default none]\n");
|
||||
}
|
||||
|
||||
void parse_args(prog_args_t *args, int argc, char **argv) {
|
||||
int opt;
|
||||
args_default(args);
|
||||
while ((opt = getopt(argc, argv, "aAoglipPcOCtdDnvrfuUsSZy")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "aAoglipPcOCtdDnvrfuUsSZyWMN")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i':
|
||||
args->input_file_name = argv[optind];
|
||||
|
@ -250,6 +254,15 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
|
|||
case 'y':
|
||||
args->cpu_affinity = atoi(argv[optind]);
|
||||
break;
|
||||
case 'W':
|
||||
output_file_name = argv[optind];
|
||||
break;
|
||||
case 'M':
|
||||
args->mbsfn_area_id = atoi(argv[optind]);
|
||||
break;
|
||||
case 'N':
|
||||
args->non_mbsfn_region = atoi(argv[optind]);
|
||||
break;
|
||||
default:
|
||||
usage(args, argv[0]);
|
||||
exit(-1);
|
||||
|
@ -278,6 +291,7 @@ void sig_int_handler(int signo)
|
|||
|
||||
cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL};
|
||||
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *t) {
|
||||
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
|
||||
|
@ -303,9 +317,9 @@ srslte_ue_sync_t ue_sync;
|
|||
prog_args_t prog_args;
|
||||
|
||||
uint32_t sfn = 0; // system frame number
|
||||
srslte_netsink_t net_sink, net_sink_signal;
|
||||
|
||||
srslte_netsink_t net_sink, net_sink_signal;
|
||||
/* Useful macros for printing lines which will disappear */
|
||||
|
||||
#define PRINT_LINE_INIT() int this_nof_lines = 0; static int prev_nof_lines = 0
|
||||
#define PRINT_LINE(_fmt, ...) printf("\033[K" _fmt "\n", ##__VA_ARGS__); this_nof_lines++
|
||||
#define PRINT_LINE_RESET_CURSOR() printf("\033[%dA", this_nof_lines); prev_nof_lines = this_nof_lines
|
||||
|
@ -317,6 +331,7 @@ int main(int argc, char **argv) {
|
|||
srslte_cell_t cell;
|
||||
int64_t sf_cnt;
|
||||
srslte_ue_mib_t ue_mib;
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
srslte_rf_t rf;
|
||||
#endif
|
||||
|
@ -324,7 +339,7 @@ int main(int argc, char **argv) {
|
|||
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
||||
int sfn_offset;
|
||||
float cfo = 0;
|
||||
|
||||
|
||||
parse_args(&prog_args, argc, argv);
|
||||
|
||||
for (int i = 0; i< SRSLTE_MAX_CODEWORDS; i++) {
|
||||
|
@ -335,6 +350,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(prog_args.cpu_affinity > -1) {
|
||||
|
||||
cpu_set_t cpuset;
|
||||
|
@ -403,6 +419,7 @@ int main(int argc, char **argv) {
|
|||
srslte_rf_set_rx_freq(&rf, prog_args.rf_freq + prog_args.file_offset_freq);
|
||||
srslte_rf_rx_wait_lo_locked(&rf);
|
||||
|
||||
|
||||
uint32_t ntrial=0;
|
||||
do {
|
||||
ret = rf_search_and_decode_mib(&rf, prog_args.rf_nof_rx_ant, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo);
|
||||
|
@ -455,7 +472,7 @@ int main(int argc, char **argv) {
|
|||
cell.nof_ports = prog_args.file_nof_ports;
|
||||
cell.nof_prb = prog_args.file_nof_prb;
|
||||
|
||||
if (srslte_ue_sync_init_file_multi(&ue_sync, prog_args.file_nof_prb,
|
||||
if (srslte_ue_sync_init_file_multi(&ue_sync, prog_args.file_nof_prb,
|
||||
prog_args.input_file_name, prog_args.file_offset_time, prog_args.file_offset_freq, prog_args.rf_nof_rx_ant)) {
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
exit(-1);
|
||||
|
@ -475,23 +492,42 @@ int main(int argc, char **argv) {
|
|||
//ue_sync.decimate = prog_args.decimate;
|
||||
}
|
||||
}
|
||||
if (srslte_ue_sync_init_multi_decim(&ue_sync, cell, srslte_rf_recv_wrapper, prog_args.rf_nof_rx_ant, (void*) &rf,decimate)) {
|
||||
if (srslte_ue_sync_init_multi_decim(&ue_sync,
|
||||
cell.nof_prb,
|
||||
cell.id==1000,
|
||||
srslte_rf_recv_wrapper,
|
||||
prog_args.rf_nof_rx_ant,
|
||||
(void*) &rf,decimate))
|
||||
{
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (srslte_ue_sync_set_cell(&ue_sync, cell))
|
||||
{
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (srslte_ue_mib_init(&ue_mib, cell)) {
|
||||
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initaiting UE MIB decoder\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
|
||||
fprintf(stderr, "Error initaiting UE MIB decoder\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (srslte_ue_dl_init(&ue_dl, cell, prog_args.rf_nof_rx_ant)) { // This is the User RNTI
|
||||
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
|
||||
fprintf(stderr, "Error initiating UE downlink processing module\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
|
||||
fprintf(stderr, "Error initiating UE downlink processing module\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
|
||||
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
}
|
||||
|
@ -499,6 +535,11 @@ int main(int argc, char **argv) {
|
|||
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
|
||||
srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);
|
||||
|
||||
/* Configure MBSFN area id and non-MBSFN Region */
|
||||
if (prog_args.mbsfn_area_id > -1) {
|
||||
srslte_ue_dl_set_mbsfn_area_id(&ue_dl, prog_args.mbsfn_area_id);
|
||||
srslte_ue_dl_set_non_mbsfn_region(&ue_dl, prog_args.non_mbsfn_region);
|
||||
}
|
||||
/* Initialize subframe counter */
|
||||
sf_cnt = 0;
|
||||
|
||||
|
@ -518,7 +559,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
// Variables for measurements
|
||||
uint32_t nframes=0;
|
||||
uint32_t ri = 0, pmi = 0;
|
||||
uint8_t ri = 0, pmi = 0;
|
||||
float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0,
|
||||
sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0;
|
||||
bool decode_pdsch = false;
|
||||
|
@ -566,10 +607,13 @@ int main(int argc, char **argv) {
|
|||
/* If a new line is detected set verbose level to Debug */
|
||||
if (fgets(input, sizeof(input), stdin)) {
|
||||
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
|
||||
ue_dl.pkt_errors = 0;
|
||||
ue_dl.pkts_total = 0;
|
||||
ue_dl.nof_detected = 0;
|
||||
nof_trials = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
|
||||
|
@ -582,9 +626,12 @@ int main(int argc, char **argv) {
|
|||
|
||||
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
|
||||
if (ret == 1) {
|
||||
|
||||
uint32_t sfidx = srslte_ue_sync_get_sfidx(&ue_sync);
|
||||
|
||||
switch (state) {
|
||||
case DECODE_MIB:
|
||||
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
|
||||
if (sfidx == 0) {
|
||||
n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error decoding UE MIB\n");
|
||||
|
@ -603,50 +650,64 @@ int main(int argc, char **argv) {
|
|||
decode_pdsch = true;
|
||||
} else {
|
||||
/* We are looking for SIB1 Blocks, search only in appropiate places */
|
||||
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
|
||||
if ((sfidx == 5 && (sfn%2)==0) || sfidx == 1) {
|
||||
decode_pdsch = true;
|
||||
} else {
|
||||
decode_pdsch = false;
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Attempting DL decode SFN=%d\n", sfn);
|
||||
if (decode_pdsch) {
|
||||
if (cell.nof_ports == 1) {
|
||||
/* Transmission mode 1 */
|
||||
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks);
|
||||
} else {
|
||||
if (prog_args.rf_nof_rx_ant == 1) {
|
||||
/* Transmission mode 2 */
|
||||
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 1, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
|
||||
acks);
|
||||
if(sfidx != 1 || prog_args.mbsfn_area_id < 0){ // Not an MBSFN subframe
|
||||
if (cell.nof_ports == 1) {
|
||||
/* Transmission mode 1 */
|
||||
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks);
|
||||
} else {
|
||||
/* Transmission mode 3 */
|
||||
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 2, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
|
||||
acks);
|
||||
if (n < 1) {
|
||||
/* Transmission mode 4 */
|
||||
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 3, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
|
||||
if (prog_args.rf_nof_rx_ant == 1) {
|
||||
/* Transmission mode 2 */
|
||||
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 1, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
|
||||
acks);
|
||||
} else {
|
||||
/* Transmission mode 3 */
|
||||
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 2, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
|
||||
acks);
|
||||
if (n < 1) {
|
||||
/* Transmission mode 4 */
|
||||
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 3, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
|
||||
acks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{ // MBSFN subframe
|
||||
n = srslte_ue_dl_decode_mbsfn(&ue_dl,
|
||||
sf_buffer,
|
||||
data[0],
|
||||
sfn*10+srslte_ue_sync_get_sfidx(&ue_sync));
|
||||
if(n>0){
|
||||
if(output_file_name){
|
||||
//srslte_filesink_init(&sink, output_file_name, SRSLTE_BYTE_BIN);
|
||||
// srslte_filesink_write(&sink, data, n);
|
||||
//srslte_filesink_free(&sink);
|
||||
}
|
||||
INFO("mbsfn PDU size is %d\n", n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (n < 0) {
|
||||
// fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
|
||||
} else if (n > 0) {
|
||||
|
||||
/* Send data if socket active */
|
||||
if (prog_args.net_port > 0) {
|
||||
if(sfidx == 1) {
|
||||
srslte_netsink_write(&net_sink, data[0], 1+(n-1)/8);
|
||||
} else {
|
||||
// FIXME: UDP Data transmission does not work
|
||||
for (uint32_t tb = 0; tb < ue_dl.pdsch_cfg.grant.nof_tb; tb++) {
|
||||
srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8);
|
||||
|
||||
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||
if (ue_dl.pdsch_cfg.grant.tb_en[tb]) {
|
||||
srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PRINT_CHANGE_SCHEDULIGN
|
||||
if (ue_dl.dl_dci.mcs_idx != old_dl_dci.mcs_idx ||
|
||||
memcmp(&ue_dl.dl_dci.type0_alloc, &old_dl_dci.type0_alloc, sizeof(srslte_ra_type0_t)) ||
|
||||
|
@ -665,6 +726,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
nof_trials++;
|
||||
|
||||
|
||||
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1f);
|
||||
rsrp0 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 0), rsrp0, 0.05f);
|
||||
rsrp1 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 1), rsrp1, 0.05f);
|
||||
|
@ -672,6 +734,7 @@ int main(int argc, char **argv) {
|
|||
enodebrate = SRSLTE_VEC_EMA((ue_dl.pdsch_cfg.grant.mcs[0].tbs + ue_dl.pdsch_cfg.grant.mcs[1].tbs)/1000.0f, enodebrate, 0.05f);
|
||||
uerate = SRSLTE_VEC_EMA(((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0))/1000.0f, uerate, 0.01f);
|
||||
|
||||
|
||||
nframes++;
|
||||
if (isnan(rsrq)) {
|
||||
rsrq = 0;
|
||||
|
@ -680,20 +743,20 @@ int main(int argc, char **argv) {
|
|||
noise = 0;
|
||||
}
|
||||
if (isnan(rsrp0)) {
|
||||
rsrp1 = 0;
|
||||
rsrp0 = 0;
|
||||
}
|
||||
if (isnan(rsrp0)) {
|
||||
rsrp1 = 0;
|
||||
if (isnan(rsrp1)) {
|
||||
rsrp1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Plot and Printf
|
||||
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5 && sfn % 20 == 0) {
|
||||
if (sfidx == 5) {
|
||||
float gain = prog_args.rf_gain;
|
||||
if (gain < 0) {
|
||||
gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc));
|
||||
}
|
||||
|
||||
|
||||
/* Print transmission scheme */
|
||||
if (ue_dl.pdsch_cfg.mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
|
||||
PRINT_LINE(" Tx scheme: %s (codebook_idx=%d)", srslte_mimotype2str(ue_dl.pdsch_cfg.mimo_type),
|
||||
|
@ -704,12 +767,15 @@ int main(int argc, char **argv) {
|
|||
|
||||
/* Print basic Parameters */
|
||||
PRINT_LINE(" nof layers: %d", ue_dl.pdsch_cfg.nof_layers);
|
||||
PRINT_LINE("nof codewords: %d", ue_dl.pdsch_cfg.grant.nof_tb);
|
||||
PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant));
|
||||
PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000);
|
||||
PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise));
|
||||
PRINT_LINE(" Rb: %6.2f / %6.2f Mbps (net/maximum)", uerate, enodebrate);
|
||||
PRINT_LINE(" PDCCH-Miss: %5.2f%%", 100 * (1 - (float) ue_dl.nof_detected / nof_trials));
|
||||
PRINT_LINE(" PDSCH-BLER: %5.2f%%", (float) 100 * ue_dl.pkt_errors / ue_dl.pkts_total);
|
||||
PRINT_LINE(" PDSCH-BLER: %5.2f%%", (float) 100 * ue_dl.pdsch_pkt_errors / ue_dl.pdsch_pkts_total);
|
||||
if(prog_args.mbsfn_area_id > -1){
|
||||
PRINT_LINE(" PMCH-BLER: %5.2f%%", (float) 100 * ue_dl.pmch_pkt_errors/ue_dl.pmch_pkts_total);
|
||||
}
|
||||
PRINT_LINE(" TB 0: mcs=%d; tbs=%d", ue_dl.pdsch_cfg.grant.mcs[0].idx,
|
||||
ue_dl.pdsch_cfg.grant.mcs[0].tbs);
|
||||
PRINT_LINE(" TB 1: mcs=%d; tbs=%d", ue_dl.pdsch_cfg.grant.mcs[1].idx,
|
||||
|
@ -751,24 +817,29 @@ int main(int argc, char **argv) {
|
|||
PRINT_LINE("Press enter maximum printing debug log of 1 subframe.");
|
||||
PRINT_LINE("");
|
||||
PRINT_LINE_RESET_CURSOR();
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) {
|
||||
if (sfidx == 9) {
|
||||
sfn++;
|
||||
if (sfn == 1024) {
|
||||
sfn = 0;
|
||||
PRINT_LINE_ADVANCE_CURSOR();
|
||||
ue_dl.pdsch_pkt_errors = 0;
|
||||
ue_dl.pdsch_pkts_total = 0;
|
||||
/*
|
||||
ue_dl.pkt_errors = 0;
|
||||
ue_dl.pkts_total = 0;
|
||||
ue_dl.pkts_total = 0;
|
||||
ue_dl.nof_detected = 0;
|
||||
nof_trials = 0;
|
||||
nof_trials = 0;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_GRAPHICS
|
||||
if (!prog_args.disable_plots) {
|
||||
if ((sfn%4) == 0 && decode_pdsch) {
|
||||
if ((sfn%3) == 0 && decode_pdsch) {
|
||||
plot_sf_idx = srslte_ue_sync_get_sfidx(&ue_sync);
|
||||
plot_track = true;
|
||||
sem_post(&plot_sem);
|
||||
|
@ -790,8 +861,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
sf_cnt++;
|
||||
} // Main loop
|
||||
printf("\033[30B\n");
|
||||
|
||||
|
||||
#ifndef DISABLE_GRAPHICS
|
||||
if (!prog_args.disable_plots) {
|
||||
if (!pthread_kill(plot_thread, 0)) {
|
||||
|
@ -812,13 +882,14 @@ int main(int argc, char **argv) {
|
|||
free(sf_buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
if (!prog_args.input_file_name) {
|
||||
srslte_ue_mib_free(&ue_mib);
|
||||
srslte_rf_close(&rf);
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("\nBye\n");
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -165,11 +165,15 @@ int main(int argc, char **argv) {
|
|||
cell.nof_prb = nof_prb;
|
||||
cell.nof_ports = 1;
|
||||
|
||||
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, nof_rx_antennas, (void*) &rf)) {
|
||||
if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, nof_rx_antennas, (void*) &rf)) {
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
uint32_t subframe_count = 0;
|
||||
bool start_capture = false;
|
||||
bool stop_capture = false;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <srslte/asn1/liblte_rrc.h>
|
||||
|
||||
namespace srslte {
|
||||
|
||||
|
@ -112,6 +113,12 @@ inline bool mnc_to_string(uint16_t mnc, std::string *str)
|
|||
*str += (mnc & 0x000F) + '0';
|
||||
return true;
|
||||
}
|
||||
inline std::string plmn_id_to_string(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
|
||||
std::string mcc_str, mnc_str;
|
||||
mnc_to_string(plmn_id.mnc, &mnc_str);
|
||||
mcc_to_string(plmn_id.mcc, &mcc_str);
|
||||
return mcc_str + mnc_str;
|
||||
}
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
available.pop();
|
||||
|
||||
if (available.size() < capacity/20) {
|
||||
printf("Warning buffer pool capacity is %f %%\n", (float) available.size()/capacity);
|
||||
printf("Warning buffer pool capacity is %f %%\n", (float) 100*available.size()/capacity);
|
||||
}
|
||||
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
if (debug_name) {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756
|
||||
#define SRSLTE_BUFFER_HEADER_OFFSET 1024
|
||||
|
||||
#define SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
//#define SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
|
||||
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
#define pool_allocate (pool->allocate(__FUNCTION__))
|
||||
|
|
|
@ -71,8 +71,9 @@ public:
|
|||
/* Timer services with ms resolution.
|
||||
* timer_id must be lower than MAC_NOF_UPPER_TIMERS
|
||||
*/
|
||||
virtual timers::timer* get(uint32_t timer_id) = 0;
|
||||
virtual uint32_t get_unique_id() = 0;
|
||||
virtual timers::timer* timer_get(uint32_t timer_id) = 0;
|
||||
virtual void timer_release_id(uint32_t timer_id) = 0;
|
||||
virtual uint32_t timer_get_unique_id() = 0;
|
||||
};
|
||||
|
||||
class read_pdu_interface
|
||||
|
|
|
@ -24,20 +24,26 @@ template<typename metrics_t>
|
|||
class metrics_listener
|
||||
{
|
||||
public:
|
||||
virtual void set_metrics(metrics_t &m) = 0;
|
||||
virtual void set_metrics(metrics_t &m, float report_period_secs=1.0) = 0;
|
||||
};
|
||||
|
||||
template<typename metrics_t>
|
||||
class metrics_hub : public periodic_thread
|
||||
{
|
||||
public:
|
||||
bool init(metrics_interface<metrics_t> *m_, float report_period_secs=1.0) {
|
||||
m = m_;
|
||||
metrics_hub()
|
||||
:m(NULL)
|
||||
,report_period_secs(1)
|
||||
{}
|
||||
bool init(metrics_interface<metrics_t> *m_, float report_period_secs_=1.0) {
|
||||
m = m_;
|
||||
report_period_secs = report_period_secs_;
|
||||
start_periodic(report_period_secs*1e6);
|
||||
return true;
|
||||
}
|
||||
void stop() {
|
||||
thread_cancel();
|
||||
wait_thread_finish();
|
||||
}
|
||||
|
||||
void add_listener(metrics_listener<metrics_t> *listener) {
|
||||
|
@ -46,15 +52,18 @@ public:
|
|||
|
||||
private:
|
||||
void run_period() {
|
||||
metrics_t metric;
|
||||
m->get_metrics(metric);
|
||||
for (uint32_t i=0;i<listeners.size();i++) {
|
||||
listeners[i]->set_metrics(metric);
|
||||
if (m) {
|
||||
metrics_t metric;
|
||||
bzero(&metric, sizeof(metrics_t));
|
||||
m->get_metrics(metric);
|
||||
for (uint32_t i=0;i<listeners.size();i++) {
|
||||
listeners[i]->set_metrics(metric, report_period_secs);
|
||||
}
|
||||
}
|
||||
}
|
||||
metrics_interface<metrics_t> *m;
|
||||
std::vector<metrics_listener<metrics_t>*> listeners;
|
||||
|
||||
std::vector<metrics_listener<metrics_t>*> listeners;
|
||||
float report_period_secs;
|
||||
};
|
||||
|
||||
} // namespace srslte
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
}
|
||||
void step() {
|
||||
if (running) {
|
||||
counter++;
|
||||
counter++;
|
||||
if (is_expired()) {
|
||||
running = false;
|
||||
if (callback) {
|
||||
|
@ -145,7 +145,7 @@ public:
|
|||
}
|
||||
uint32_t get_unique_id() {
|
||||
if (nof_used_timers >= nof_timers) {
|
||||
fprintf(stderr, "Error getting uinque timer id: no more timers available\n");
|
||||
fprintf(stderr, "Error getting unique timer id: no more timers available\n");
|
||||
return 0;
|
||||
} else {
|
||||
while(used_timers[next_timer]) {
|
||||
|
|
|
@ -244,7 +244,7 @@ public:
|
|||
class gtpu_interface_rrc
|
||||
{
|
||||
public:
|
||||
virtual void add_bearer(uint16_t rnti, uint32_t lcid, uint32_t teid_out, uint32_t *teid_in) = 0;
|
||||
virtual void add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, uint32_t *teid_in) = 0;
|
||||
virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0;
|
||||
virtual void rem_user(uint16_t rnti) = 0;
|
||||
};
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "upper/common_enb.h"
|
||||
#include "upper/s1ap_metrics.h"
|
||||
#include "upper/rrc_metrics.h"
|
||||
#include "srslte/upper/gw_metrics.h"
|
||||
#include "../../../../srsue/hdr/upper/gw_metrics.h"
|
||||
#include "srslte/upper/rlc_metrics.h"
|
||||
#include "mac/mac_metrics.h"
|
||||
#include "phy/phy_metrics.h"
|
||||
|
|
|
@ -54,6 +54,7 @@ class usim_interface_nas
|
|||
public:
|
||||
virtual void get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0;
|
||||
virtual void get_imei_vec(uint8_t* imei_, uint32_t n) = 0;
|
||||
virtual int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 0;
|
||||
virtual void generate_authentication_response(uint8_t *rand,
|
||||
uint8_t *autn_enb,
|
||||
uint16_t mcc,
|
||||
|
@ -98,10 +99,28 @@ class nas_interface_rrc
|
|||
{
|
||||
public:
|
||||
virtual bool is_attached() = 0;
|
||||
virtual bool is_attaching() = 0;
|
||||
virtual void notify_connection_setup() = 0;
|
||||
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
|
||||
virtual uint32_t get_ul_count() = 0;
|
||||
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;
|
||||
virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
|
||||
virtual void plmn_search_end() = 0;
|
||||
};
|
||||
|
||||
// NAS interface for UE
|
||||
class nas_interface_ue
|
||||
{
|
||||
public:
|
||||
virtual void attach_request() = 0;
|
||||
virtual void deattach_request() = 0;
|
||||
};
|
||||
|
||||
// NAS interface for UE
|
||||
class nas_interface_gw
|
||||
{
|
||||
public:
|
||||
virtual void attach_request() = 0;
|
||||
};
|
||||
|
||||
// RRC interface for MAC
|
||||
|
@ -123,6 +142,8 @@ class rrc_interface_phy
|
|||
public:
|
||||
virtual void in_sync() = 0;
|
||||
virtual void out_of_sync() = 0;
|
||||
virtual void earfcn_end() = 0;
|
||||
virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0;
|
||||
};
|
||||
|
||||
// RRC interface for NAS
|
||||
|
@ -133,18 +154,11 @@ public:
|
|||
virtual uint16_t get_mcc() = 0;
|
||||
virtual uint16_t get_mnc() = 0;
|
||||
virtual void enable_capabilities() = 0;
|
||||
virtual void plmn_search() = 0;
|
||||
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0;
|
||||
virtual std::string get_rb_name(uint32_t lcid) = 0;
|
||||
};
|
||||
|
||||
// RRC interface for GW
|
||||
class rrc_interface_gw
|
||||
{
|
||||
public:
|
||||
virtual bool rrc_connected() = 0;
|
||||
virtual void rrc_connect() = 0;
|
||||
virtual bool have_drb() = 0;
|
||||
};
|
||||
|
||||
// RRC interface for PDCP
|
||||
class rrc_interface_pdcp
|
||||
{
|
||||
|
@ -169,6 +183,7 @@ class pdcp_interface_gw
|
|||
{
|
||||
public:
|
||||
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
|
||||
virtual bool is_drb_enabled(uint32_t lcid) = 0;
|
||||
};
|
||||
|
||||
// PDCP interface for RRC
|
||||
|
@ -281,6 +296,8 @@ public:
|
|||
bool last_ndi[SRSLTE_MAX_CODEWORDS];
|
||||
uint32_t n_bytes[SRSLTE_MAX_CODEWORDS];
|
||||
int rv[SRSLTE_MAX_CODEWORDS];
|
||||
bool tb_en[SRSLTE_MAX_CODEWORDS];
|
||||
bool tb_cw_swap;
|
||||
uint16_t rnti;
|
||||
bool is_from_rar;
|
||||
bool is_sps_release;
|
||||
|
@ -290,11 +307,11 @@ public:
|
|||
} mac_grant_t;
|
||||
|
||||
typedef struct {
|
||||
bool decode_enabled;
|
||||
bool decode_enabled[SRSLTE_MAX_TB];
|
||||
int rv[SRSLTE_MAX_TB];
|
||||
uint16_t rnti;
|
||||
bool generate_ack;
|
||||
bool default_ack;
|
||||
bool default_ack[SRSLTE_MAX_TB];
|
||||
// If non-null, called after tb_decoded_ok to determine if ack needs to be sent
|
||||
bool (*generate_ack_callback)(void*);
|
||||
void *generate_ack_callback_arg;
|
||||
|
@ -421,8 +438,8 @@ typedef struct {
|
|||
int worker_cpu_mask;
|
||||
int sync_cpu_affinity;
|
||||
|
||||
uint32_t nof_rx_ant;
|
||||
std::string equalizer_mode;
|
||||
uint32_t nof_rx_ant;
|
||||
std::string equalizer_mode;
|
||||
int cqi_max;
|
||||
int cqi_fixed;
|
||||
float snr_ema_coeff;
|
||||
|
@ -442,9 +459,8 @@ class phy_interface_mac_common
|
|||
{
|
||||
public:
|
||||
/* Start synchronization with strongest cell in the current carrier frequency */
|
||||
virtual void sync_start() = 0;
|
||||
virtual void sync_stop() = 0;
|
||||
|
||||
virtual bool sync_status() = 0;
|
||||
|
||||
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
|
||||
virtual void set_crnti(uint16_t rnti) = 0;
|
||||
|
||||
|
@ -511,16 +527,21 @@ public:
|
|||
virtual void set_config_common(phy_cfg_common_t *common) = 0;
|
||||
virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0;
|
||||
virtual void set_config_64qam_en(bool enable) = 0;
|
||||
|
||||
|
||||
/* Cell search and selection procedures */
|
||||
virtual void cell_search_start() = 0;
|
||||
virtual void cell_search_stop() = 0;
|
||||
virtual void cell_search_next() = 0;
|
||||
virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0;
|
||||
|
||||
/* Is the PHY downlink synchronized? */
|
||||
virtual bool status_is_sync() = 0;
|
||||
virtual bool sync_status() = 0;
|
||||
virtual void sync_reset() = 0;
|
||||
|
||||
/* Configure UL using parameters written with set_param() */
|
||||
virtual void configure_ul_params(bool pregen_disabled = false) = 0;
|
||||
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void resync_sfn() = 0;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -60,7 +60,10 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
srslte_cell_t cell;
|
||||
srslte_refsignal_cs_t csr_signal;
|
||||
srslte_refsignal_t csr_refs;
|
||||
srslte_refsignal_t **mbsfn_refs;
|
||||
|
||||
|
||||
cf_t *pilot_estimates;
|
||||
cf_t *pilot_estimates_average;
|
||||
cf_t *pilot_recv_signal;
|
||||
|
@ -75,7 +78,7 @@ typedef struct {
|
|||
|
||||
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
|
||||
srslte_interp_lin_t srslte_interp_lin;
|
||||
|
||||
srslte_interp_lin_t srslte_interp_lin_mbsfn;
|
||||
float rssi[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
float rsrp[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
|
@ -92,9 +95,16 @@ typedef struct {
|
|||
|
||||
|
||||
SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q,
|
||||
srslte_cell_t cell);
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
|
||||
|
||||
|
||||
SRSLTE_API int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t *q,
|
||||
uint16_t mbsfn_area_id);
|
||||
SRSLTE_API int srslte_chest_dl_set_cell(srslte_chest_dl_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
|
||||
|
||||
SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q,
|
||||
float *filter,
|
||||
|
@ -106,6 +116,8 @@ SRSLTE_API void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q,
|
|||
SRSLTE_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q,
|
||||
srslte_chest_dl_noise_alg_t noise_estimation_alg);
|
||||
|
||||
|
||||
|
||||
SRSLTE_API int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q,
|
||||
cf_t *input[SRSLTE_MAX_PORTS],
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
|
@ -117,6 +129,14 @@ SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
|
|||
cf_t *ce[SRSLTE_MAX_PORTS],
|
||||
uint32_t sf_idx);
|
||||
|
||||
SRSLTE_API int srslte_chest_dl_estimate_multi_mbsfn(srslte_chest_dl_t *q,
|
||||
cf_t *input[SRSLTE_MAX_PORTS],
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
uint32_t sf_idx,
|
||||
uint32_t nof_rx_antennas,
|
||||
uint16_t mbsfn_area_id);
|
||||
|
||||
|
||||
SRSLTE_API int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q,
|
||||
cf_t *input,
|
||||
cf_t *ce,
|
||||
|
|
|
@ -77,9 +77,13 @@ typedef struct {
|
|||
|
||||
|
||||
SRSLTE_API int srslte_chest_ul_init(srslte_chest_ul_t *q,
|
||||
srslte_cell_t cell);
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_chest_ul_free(srslte_chest_ul_t *q);
|
||||
|
||||
SRSLTE_API int srslte_chest_ul_set_cell(srslte_chest_ul_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_chest_ul_free(srslte_chest_ul_t *q);
|
||||
|
||||
SRSLTE_API void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
|
|
|
@ -40,22 +40,34 @@
|
|||
|
||||
// Number of references in a subframe: there are 2 symbols for port_id=0,1 x 2 slots x 2 refs per prb
|
||||
#define SRSLTE_REFSIGNAL_NUM_SF(nof_prb, port_id) (((port_id)<2?8:4)*(nof_prb))
|
||||
#define SRSLTE_REFSIGNAL_NUM_SF_MBSFN(nof_prb, port_id) ((2 + 18)*(nof_prb))
|
||||
|
||||
#define SRSLTE_REFSIGNAL_MAX_NUM_SF(nof_prb) SRSLTE_REFSIGNAL_NUM_SF(nof_prb, 0)
|
||||
#define SRSLTE_REFSIGNAL_MAX_NUM_SF_MBSFN(nof_prb) SRSLTE_REFSIGNAL_NUM_SF_MBSFN(nof_prb,0)
|
||||
|
||||
#define SRSLTE_REFSIGNAL_PILOT_IDX(i,l,cell) (2*cell.nof_prb*(l)+(i))
|
||||
|
||||
#define SRSLTE_REFSIGNAL_PILOT_IDX_MBSFN(i,l,cell) ((6*cell.nof_prb*(l)+(i)))
|
||||
|
||||
|
||||
|
||||
/** Cell-Specific Reference Signal */
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_cell_t cell;
|
||||
cf_t *pilots[2][SRSLTE_NSUBFRAMES_X_FRAME]; // Saves the reference signal per subframe for ports 0,1 and ports 2,3
|
||||
} srslte_refsignal_cs_t;
|
||||
cf_t *pilots[2][SRSLTE_NSUBFRAMES_X_FRAME]; // Saves the reference signal per subframe for ports 0,1 and ports 2,3
|
||||
srslte_sf_t type;
|
||||
uint16_t mbsfn_area_id;
|
||||
} srslte_refsignal_t;
|
||||
|
||||
|
||||
SRSLTE_API int srslte_refsignal_cs_init(srslte_refsignal_cs_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_refsignal_cs_free(srslte_refsignal_cs_t *q);
|
||||
SRSLTE_API int srslte_refsignal_cs_init(srslte_refsignal_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_cs_set_cell(srslte_refsignal_t * q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_refsignal_free(srslte_refsignal_t *q);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_cs_put_sf(srslte_cell_t cell,
|
||||
uint32_t port_id,
|
||||
|
@ -81,4 +93,29 @@ SRSLTE_API uint32_t srslte_refsignal_cs_v(uint32_t port_id,
|
|||
|
||||
SRSLTE_API uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_mbsfn_init(srslte_refsignal_t *q, srslte_cell_t cell,
|
||||
uint16_t mbsfn_area_id);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_mbsfn_get_sf(srslte_cell_t cell,
|
||||
uint32_t port_id,
|
||||
cf_t *sf_symbols,
|
||||
cf_t *pilots);
|
||||
|
||||
SRSLTE_API uint32_t srslte_refsignal_mbsfn_nsymbol(uint32_t l);
|
||||
|
||||
SRSLTE_API uint32_t srslte_refsignal_mbsfn_fidx(uint32_t l);
|
||||
|
||||
SRSLTE_API uint32_t srslte_refsignal_mbsfn_nof_symbols();
|
||||
|
||||
SRSLTE_API int srslte_refsignal_mbsfn_put_sf(srslte_cell_t cell,
|
||||
uint32_t port_id,
|
||||
cf_t *cs_pilots,
|
||||
cf_t *mbsfn_pilots,
|
||||
cf_t *sf_symbols);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_mbsfn_gen_seq(srslte_refsignal_t * q,
|
||||
srslte_cell_t cell,
|
||||
uint32_t N_mbsfn_id);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,7 +94,10 @@ typedef struct {
|
|||
} srslte_refsignal_srs_pregen_t;
|
||||
|
||||
SRSLTE_API int srslte_refsignal_ul_init(srslte_refsignal_ul_t *q,
|
||||
srslte_cell_t cell);
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q);
|
||||
|
||||
|
@ -115,9 +118,13 @@ SRSLTE_API uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m,
|
|||
|
||||
SRSLTE_API bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *cfg,
|
||||
uint32_t nof_prb);
|
||||
uint32_t nof_prb);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q,
|
||||
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q,
|
||||
srslte_refsignal_ul_dmrs_pregen_t *pregen,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q,
|
||||
srslte_refsignal_ul_dmrs_pregen_t *pregen);
|
||||
|
||||
SRSLTE_API void srslte_refsignal_dmrs_pusch_pregen_free(srslte_refsignal_ul_t *q,
|
||||
|
|
|
@ -63,7 +63,11 @@
|
|||
#define SRSLTE_LTE_CRC16 0x11021
|
||||
#define SRSLTE_LTE_CRC8 0x19B
|
||||
|
||||
#define SRSLTE_MAX_MBSFN_AREA_IDS 256
|
||||
#define SRSLTE_PMCH_RV 0
|
||||
|
||||
typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t;
|
||||
typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
|
||||
|
||||
|
||||
#define SRSLTE_CRNTI_START 0x000B
|
||||
|
@ -130,6 +134,13 @@ typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t;
|
|||
|| l == SRSLTE_CP_NSYMB(cp) - 3)
|
||||
|
||||
|
||||
|
||||
#define SRSLTE_SYMBOL_HAS_REF_MBSFN(l, s) ((l == 2 && s == 0) || (l == 0 && s == 1) || (l == 4 && s == 1))
|
||||
|
||||
#define SRSLTE_NON_MBSFN_REGION_GUARD_LENGTH(non_mbsfn_region,symbol_sz) ((non_mbsfn_region == 1)?(SRSLTE_CP_LEN_EXT(symbol_sz) - SRSLTE_CP_LEN_NORM(0, symbol_sz)):(2*SRSLTE_CP_LEN_EXT(symbol_sz) - SRSLTE_CP_LEN_NORM(0, symbol_sz)- SRSLTE_CP_LEN_NORM(1, symbol_sz)))
|
||||
|
||||
|
||||
|
||||
#define SRSLTE_NOF_LTE_BANDS 38
|
||||
|
||||
#define SRSLTE_DEFAULT_MAX_FRAMES_PBCH 500
|
||||
|
@ -157,6 +168,7 @@ typedef enum {
|
|||
SRSLTE_RNTI_TEMP, /* Temporary C-RNTI */
|
||||
SRSLTE_RNTI_SPS, /* Semi-Persistent Scheduling C-RNTI */
|
||||
SRSLTE_RNTI_PCH, /* Paging RNTI */
|
||||
SRSLTE_RNTI_MBSFN,
|
||||
SRSLTE_RNTI_NOF_TYPES
|
||||
} srslte_rnti_type_t;
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ typedef struct SRSLTE_API {
|
|||
uint8_t *c_bytes;
|
||||
float *c_float;
|
||||
short *c_short;
|
||||
uint32_t len;
|
||||
uint32_t cur_len;
|
||||
uint32_t max_len;
|
||||
} srslte_sequence_t;
|
||||
|
||||
SRSLTE_API int srslte_sequence_init(srslte_sequence_t *q, uint32_t len);
|
||||
|
@ -55,8 +56,9 @@ SRSLTE_API int srslte_sequence_LTE_pr(srslte_sequence_t *q,
|
|||
uint32_t len,
|
||||
uint32_t seed);
|
||||
|
||||
SRSLTE_API void srslte_sequence_set_LTE_pr(srslte_sequence_t *q,
|
||||
uint32_t seed);
|
||||
SRSLTE_API int srslte_sequence_set_LTE_pr(srslte_sequence_t *q,
|
||||
uint32_t len,
|
||||
uint32_t seed);
|
||||
|
||||
SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t *seq,
|
||||
srslte_cp_t cp,
|
||||
|
@ -92,4 +94,10 @@ SRSLTE_API int srslte_sequence_pucch(srslte_sequence_t *seq,
|
|||
uint16_t rnti,
|
||||
uint32_t nslot,
|
||||
uint32_t cell_id);
|
||||
|
||||
SRSLTE_API int srslte_sequence_pmch(srslte_sequence_t *seq,
|
||||
uint32_t nslot,
|
||||
uint32_t mbsfn_id,
|
||||
uint32_t len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -58,6 +58,7 @@ typedef enum {
|
|||
}srslte_dft_dir_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
int init_size; // DFT length used in the first initialization
|
||||
int size; // DFT length
|
||||
void *in; // Input buffer
|
||||
void *out; // Output buffer
|
||||
|
@ -80,7 +81,7 @@ SRSLTE_API int srslte_dft_plan(srslte_dft_plan_t *plan,
|
|||
srslte_dft_dir_t dir,
|
||||
srslte_dft_mode_t type);
|
||||
|
||||
SRSLTE_API int srslte_dft_plan_c(srslte_dft_plan_t *plan,
|
||||
SRSLTE_API int srslte_dft_plan_c(srslte_dft_plan_t *plan,
|
||||
int dft_points,
|
||||
srslte_dft_dir_t dir);
|
||||
|
||||
|
@ -88,6 +89,16 @@ SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
|
|||
int dft_points,
|
||||
srslte_dft_dir_t dir);
|
||||
|
||||
SRSLTE_API int srslte_dft_replan(srslte_dft_plan_t *plan,
|
||||
const int new_dft_points);
|
||||
|
||||
SRSLTE_API int srslte_dft_replan_c(srslte_dft_plan_t *plan,
|
||||
int new_dft_points);
|
||||
|
||||
SRSLTE_API int srslte_dft_replan_r(srslte_dft_plan_t *plan,
|
||||
int new_dft_points);
|
||||
|
||||
|
||||
SRSLTE_API void srslte_dft_plan_free(srslte_dft_plan_t *plan);
|
||||
|
||||
/* Set options */
|
||||
|
|
|
@ -45,12 +45,18 @@ typedef struct SRSLTE_API {
|
|||
|
||||
uint32_t max_prb;
|
||||
srslte_dft_plan_t dft_plan[SRSLTE_MAX_PRB+1];
|
||||
srslte_dft_plan_t idft_plan[SRSLTE_MAX_PRB+1];
|
||||
|
||||
|
||||
}srslte_dft_precoding_t;
|
||||
|
||||
SRSLTE_API int srslte_dft_precoding_init(srslte_dft_precoding_t *q,
|
||||
uint32_t max_prb);
|
||||
SRSLTE_API int srslte_dft_precoding_init(srslte_dft_precoding_t *q,
|
||||
uint32_t max_prb,
|
||||
bool is_tx);
|
||||
|
||||
SRSLTE_API int srslte_dft_precoding_init_tx(srslte_dft_precoding_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API int srslte_dft_precoding_init_rx(srslte_dft_precoding_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_dft_precoding_free(srslte_dft_precoding_t *q);
|
||||
|
||||
|
@ -62,10 +68,4 @@ SRSLTE_API int srslte_dft_precoding(srslte_dft_precoding_t *q,
|
|||
uint32_t nof_prb,
|
||||
uint32_t nof_symbols);
|
||||
|
||||
SRSLTE_API int srslte_dft_predecoding(srslte_dft_precoding_t *q,
|
||||
cf_t *input,
|
||||
cf_t *output,
|
||||
uint32_t nof_prb,
|
||||
uint32_t nof_symbols);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
/* This is common for both directions */
|
||||
typedef struct SRSLTE_API{
|
||||
srslte_dft_plan_t fft_plan;
|
||||
uint32_t max_prb;
|
||||
uint32_t nof_symbols;
|
||||
uint32_t symbol_sz;
|
||||
uint32_t nof_guards;
|
||||
|
@ -55,7 +56,14 @@ typedef struct SRSLTE_API{
|
|||
srslte_cp_t cp;
|
||||
cf_t *tmp; // for removing zero padding
|
||||
|
||||
bool mbsfn_subframe;
|
||||
uint32_t mbsfn_guard_len;
|
||||
uint32_t nof_symbols_mbsfn;
|
||||
uint8_t non_mbsfn_region;
|
||||
|
||||
|
||||
bool freq_shift;
|
||||
float freq_shift_f;
|
||||
cf_t *shift_buffer;
|
||||
}srslte_ofdm_t;
|
||||
|
||||
|
@ -63,11 +71,32 @@ SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
|
|||
srslte_cp_t cp,
|
||||
int symbol_sz,
|
||||
int nof_prb,
|
||||
srslte_dft_dir_t dir);
|
||||
srslte_dft_dir_t dir);
|
||||
|
||||
SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q,
|
||||
srslte_cp_t cp,
|
||||
int symbol_sz,
|
||||
int nof_prb,
|
||||
srslte_dft_dir_t dir,
|
||||
srslte_sf_t sf_type);
|
||||
|
||||
SRSLTE_API int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q,
|
||||
srslte_cp_t cp_type,
|
||||
uint32_t nof_prb);
|
||||
|
||||
|
||||
|
||||
SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q,
|
||||
srslte_cp_t cp_type,
|
||||
uint32_t nof_prb);
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q,
|
||||
srslte_cp_t cp,
|
||||
uint32_t nof_prb);
|
||||
|
||||
SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q,
|
||||
srslte_cp_t cp,
|
||||
uint32_t nof_prb);
|
||||
|
||||
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q);
|
||||
|
||||
|
@ -85,12 +114,22 @@ SRSLTE_API int srslte_ofdm_tx_init(srslte_ofdm_t *q,
|
|||
srslte_cp_t cp_type,
|
||||
uint32_t nof_prb);
|
||||
|
||||
SRSLTE_API int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q,
|
||||
srslte_cp_t cp,
|
||||
uint32_t nof_prb);
|
||||
|
||||
|
||||
SRSLTE_API void srslte_ofdm_tx_free(srslte_ofdm_t *q);
|
||||
|
||||
SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q,
|
||||
cf_t *input,
|
||||
cf_t *output);
|
||||
|
||||
SRSLTE_API void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q,
|
||||
cf_t *input,
|
||||
cf_t *output);
|
||||
|
||||
|
||||
SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q,
|
||||
cf_t *input,
|
||||
cf_t *output);
|
||||
|
@ -101,4 +140,8 @@ SRSLTE_API int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q,
|
|||
SRSLTE_API void srslte_ofdm_set_normalize(srslte_ofdm_t *q,
|
||||
bool normalize_enable);
|
||||
|
||||
#endif
|
||||
SRSLTE_API void srslte_ofdm_set_non_mbsfn_region(srslte_ofdm_t *q,
|
||||
uint8_t non_mbsfn_region);
|
||||
|
||||
|
||||
#endif
|
|
@ -76,7 +76,7 @@ typedef struct SRSLTE_API {
|
|||
srslte_pdsch_t pdsch;
|
||||
srslte_phich_t phich;
|
||||
|
||||
srslte_refsignal_cs_t csr_signal;
|
||||
srslte_refsignal_t csr_signal;
|
||||
srslte_pdsch_cfg_t pdsch_cfg;
|
||||
srslte_ra_dl_dci_t dl_dci;
|
||||
|
||||
|
@ -88,6 +88,8 @@ typedef struct SRSLTE_API {
|
|||
float sss_signal5[SRSLTE_SSS_LEN];
|
||||
|
||||
float tx_amp;
|
||||
|
||||
uint8_t tmp[1024*128];
|
||||
|
||||
} srslte_enb_dl_t;
|
||||
|
||||
|
@ -108,11 +110,14 @@ typedef struct {
|
|||
|
||||
/* This function shall be called just after the initial synchronization */
|
||||
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q,
|
||||
srslte_cell_t cell);
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q);
|
||||
|
||||
SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q,
|
||||
SRSLTE_API int srslte_enb_dl_set_cell(srslte_enb_dl_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q,
|
||||
uint32_t cfi);
|
||||
|
||||
SRSLTE_API void srslte_enb_dl_set_amp(srslte_enb_dl_t *q,
|
||||
|
@ -154,16 +159,18 @@ SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q,
|
|||
srslte_ra_dl_grant_t *grant,
|
||||
srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
|
||||
uint16_t rnti,
|
||||
uint32_t rv_idx,
|
||||
int rv_idx[SRSLTE_MAX_CODEWORDS],
|
||||
uint32_t sf_idx,
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS]);
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS],
|
||||
srslte_mimo_type_t mimo_type,
|
||||
uint32_t pmi);
|
||||
|
||||
SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q,
|
||||
srslte_ra_dl_dci_t *grant,
|
||||
srslte_dci_format_t format,
|
||||
srslte_dci_location_t location,
|
||||
uint16_t rnti,
|
||||
uint32_t sf_idx);
|
||||
uint32_t sf_idx);
|
||||
|
||||
SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q,
|
||||
srslte_ra_ul_dci_t *grant,
|
||||
|
@ -171,5 +178,12 @@ SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q,
|
|||
uint16_t rnti,
|
||||
uint32_t sf_idx);
|
||||
|
||||
SRSLTE_API void srslte_enb_dl_save_signal(srslte_enb_dl_t *q,
|
||||
srslte_softbuffer_tx_t *softbuffer,
|
||||
uint8_t *data,
|
||||
uint32_t tti,
|
||||
uint32_t rv_idx,
|
||||
uint16_t rnti,
|
||||
uint32_t cfi);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -100,15 +100,18 @@ typedef struct {
|
|||
} srslte_enb_ul_pusch_t;
|
||||
|
||||
/* This function shall be called just after the initial synchronization */
|
||||
SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
|
||||
srslte_cell_t cell,
|
||||
srslte_prach_cfg_t* prach_cfg,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg);
|
||||
SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q);
|
||||
|
||||
SRSLTE_API int srslte_enb_ul_set_cell(srslte_enb_ul_t *q,
|
||||
srslte_cell_t cell,
|
||||
srslte_prach_cfg_t* prach_cfg,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg);
|
||||
|
||||
SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q,
|
||||
uint16_t rnti);
|
||||
|
||||
|
|
|
@ -50,20 +50,14 @@
|
|||
#define SRSLTE_TCOD_MAX_LEN_CODED (SRSLTE_TCOD_RATE*SRSLTE_TCOD_MAX_LEN_CB+SRSLTE_TCOD_TOTALTAIL)
|
||||
|
||||
#include "srslte/phy/fec/turbodecoder_gen.h"
|
||||
|
||||
#ifdef LV_HAVE_SSE
|
||||
#include "srslte/phy/fec/turbodecoder_simd.h"
|
||||
#else
|
||||
#define SRSLTE_TDEC_NPAR 1
|
||||
#endif
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
#ifdef LV_HAVE_SSE
|
||||
srslte_tdec_simd_t tdec_simd;
|
||||
#else
|
||||
float *input_conv;
|
||||
srslte_tdec_gen_t tdec_gen;
|
||||
#endif
|
||||
float *input_conv;
|
||||
union {
|
||||
srslte_tdec_simd_t tdec_simd;
|
||||
srslte_tdec_gen_t tdec_gen;
|
||||
};
|
||||
} srslte_tdec_t;
|
||||
|
||||
SRSLTE_API int srslte_tdec_init(srslte_tdec_t * h,
|
||||
|
@ -80,7 +74,7 @@ SRSLTE_API int srslte_tdec_reset_cb(srslte_tdec_t * h,
|
|||
SRSLTE_API int srslte_tdec_get_nof_iterations_cb(srslte_tdec_t * h,
|
||||
uint32_t cb_idx);
|
||||
|
||||
SRSLTE_API int srslte_tdec_get_nof_parallel(srslte_tdec_t * h);
|
||||
SRSLTE_API uint32_t srslte_tdec_get_nof_parallel(srslte_tdec_t * h);
|
||||
|
||||
SRSLTE_API void srslte_tdec_iteration(srslte_tdec_t * h,
|
||||
int16_t* input,
|
||||
|
@ -101,15 +95,15 @@ SRSLTE_API int srslte_tdec_run_all(srslte_tdec_t * h,
|
|||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_iteration_par(srslte_tdec_t * h,
|
||||
int16_t* input[SRSLTE_TDEC_NPAR],
|
||||
int16_t* input[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_decision_par(srslte_tdec_t * h,
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_decision_byte_par(srslte_tdec_t * h,
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_decision_byte_par_cb(srslte_tdec_t * h,
|
||||
|
@ -118,8 +112,8 @@ SRSLTE_API void srslte_tdec_decision_byte_par_cb(srslte_tdec_t * h,
|
|||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API int srslte_tdec_run_all_par(srslte_tdec_t * h,
|
||||
int16_t * input[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
int16_t * input[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_iterations,
|
||||
uint32_t long_cb);
|
||||
|
||||
|
|
|
@ -43,23 +43,8 @@
|
|||
#include "srslte/phy/fec/tc_interl.h"
|
||||
#include "srslte/phy/fec/cbsegm.h"
|
||||
|
||||
//#define ENABLE_SIMD_INTER
|
||||
|
||||
// The constant SRSLTE_TDEC_NPAR defines the maximum number of parallel CB supported by all SIMD decoders
|
||||
#ifdef ENABLE_SIMD_INTER
|
||||
#include "srslte/phy/fec/turbodecoder_simd_inter.h"
|
||||
#ifdef LV_HAVE_AVX2
|
||||
#define SRSLTE_TDEC_NPAR_INTRA 2
|
||||
#else
|
||||
#define SRSLTE_TDEC_NPAR_INTRA 1
|
||||
#endif
|
||||
#else
|
||||
#ifdef LV_HAVE_AVX2
|
||||
#define SRSLTE_TDEC_NPAR 2
|
||||
#else
|
||||
#define SRSLTE_TDEC_NPAR 1
|
||||
#endif
|
||||
#endif
|
||||
// Define maximum number of CB decoded in parallel (2 for AVX2)
|
||||
#define SRSLTE_TDEC_MAX_NPAR 2
|
||||
|
||||
#define SRSLTE_TCOD_RATE 3
|
||||
#define SRSLTE_TCOD_TOTALTAIL 12
|
||||
|
@ -80,18 +65,18 @@ typedef struct SRSLTE_API {
|
|||
|
||||
map_gen_t dec;
|
||||
|
||||
int16_t *app1[SRSLTE_TDEC_NPAR];
|
||||
int16_t *app2[SRSLTE_TDEC_NPAR];
|
||||
int16_t *ext1[SRSLTE_TDEC_NPAR];
|
||||
int16_t *ext2[SRSLTE_TDEC_NPAR];
|
||||
int16_t *syst[SRSLTE_TDEC_NPAR];
|
||||
int16_t *parity0[SRSLTE_TDEC_NPAR];
|
||||
int16_t *parity1[SRSLTE_TDEC_NPAR];
|
||||
int16_t *app1[SRSLTE_TDEC_MAX_NPAR];
|
||||
int16_t *app2[SRSLTE_TDEC_MAX_NPAR];
|
||||
int16_t *ext1[SRSLTE_TDEC_MAX_NPAR];
|
||||
int16_t *ext2[SRSLTE_TDEC_MAX_NPAR];
|
||||
int16_t *syst[SRSLTE_TDEC_MAX_NPAR];
|
||||
int16_t *parity0[SRSLTE_TDEC_MAX_NPAR];
|
||||
int16_t *parity1[SRSLTE_TDEC_MAX_NPAR];
|
||||
|
||||
int cb_mask;
|
||||
int current_cbidx;
|
||||
srslte_tc_interl_t interleaver[SRSLTE_NOF_TC_CB_SIZES];
|
||||
int n_iter[SRSLTE_TDEC_NPAR];
|
||||
int n_iter[SRSLTE_TDEC_MAX_NPAR];
|
||||
} srslte_tdec_simd_t;
|
||||
|
||||
SRSLTE_API int srslte_tdec_simd_init(srslte_tdec_simd_t * h,
|
||||
|
@ -103,6 +88,8 @@ SRSLTE_API void srslte_tdec_simd_free(srslte_tdec_simd_t * h);
|
|||
SRSLTE_API int srslte_tdec_simd_reset(srslte_tdec_simd_t * h,
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API
|
||||
|
||||
SRSLTE_API int srslte_tdec_simd_get_nof_iterations_cb(srslte_tdec_simd_t * h,
|
||||
uint32_t cb_idx);
|
||||
|
||||
|
@ -110,15 +97,15 @@ SRSLTE_API int srslte_tdec_simd_reset_cb(srslte_tdec_simd_t * h,
|
|||
uint32_t cb_idx);
|
||||
|
||||
SRSLTE_API void srslte_tdec_simd_iteration(srslte_tdec_simd_t * h,
|
||||
int16_t * input[SRSLTE_TDEC_NPAR],
|
||||
int16_t * input[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_simd_decision(srslte_tdec_simd_t * h,
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_simd_decision_byte(srslte_tdec_simd_t * h,
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_simd_decision_byte_cb(srslte_tdec_simd_t * h,
|
||||
|
@ -127,8 +114,8 @@ SRSLTE_API void srslte_tdec_simd_decision_byte_cb(srslte_tdec_simd_t * h,
|
|||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API int srslte_tdec_simd_run_all(srslte_tdec_simd_t * h,
|
||||
int16_t * input[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
int16_t * input[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_iterations,
|
||||
uint32_t long_cb);
|
||||
|
||||
|
|
|
@ -49,9 +49,9 @@
|
|||
#include "srslte/phy/fec/cbsegm.h"
|
||||
|
||||
#if LV_HAVE_AVX2
|
||||
#define SRSLTE_TDEC_NPAR 16
|
||||
#define SRSLTE_TDEC_MAX_NPAR 16
|
||||
#else
|
||||
#define SRSLTE_TDEC_NPAR 8
|
||||
#define SRSLTE_TDEC_MAX_NPAR 8
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -71,7 +71,7 @@ typedef struct SRSLTE_API {
|
|||
int current_cbidx;
|
||||
uint32_t current_long_cb;
|
||||
srslte_tc_interl_t interleaver[SRSLTE_NOF_TC_CB_SIZES];
|
||||
int n_iter[SRSLTE_TDEC_NPAR];
|
||||
int n_iter[SRSLTE_TDEC_MAX_NPAR];
|
||||
} srslte_tdec_simd_inter_t;
|
||||
|
||||
SRSLTE_API int srslte_tdec_simd_inter_init(srslte_tdec_simd_inter_t * h,
|
||||
|
@ -90,17 +90,17 @@ SRSLTE_API int srslte_tdec_simd_inter_reset_cb(srslte_tdec_simd_inter_t * h,
|
|||
uint32_t cb_idx);
|
||||
|
||||
SRSLTE_API void srslte_tdec_simd_inter_iteration(srslte_tdec_simd_inter_t * h,
|
||||
int16_t * input[SRSLTE_TDEC_NPAR],
|
||||
int16_t * input[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_cb,
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_simd_inter_decision(srslte_tdec_simd_inter_t * h,
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_cb,
|
||||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API void srslte_tdec_simd_inter_decision_byte(srslte_tdec_simd_inter_t * h,
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_cb,
|
||||
uint32_t long_cb);
|
||||
|
||||
|
@ -110,8 +110,8 @@ SRSLTE_API void srslte_tdec_simd_inter_decision_byte_cb(srslte_tdec_simd_inter_t
|
|||
uint32_t long_cb);
|
||||
|
||||
SRSLTE_API int srslte_tdec_simd_inter_run_all(srslte_tdec_simd_inter_t * h,
|
||||
int16_t *input[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
int16_t *input[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_iterations,
|
||||
uint32_t nof_cb,
|
||||
uint32_t long_cb);
|
||||
|
|
|
@ -41,11 +41,14 @@
|
|||
#include "srslte/phy/common/phy_common.h"
|
||||
|
||||
#define SRSLTE_CQI_MAX_BITS 64
|
||||
#define SRSLTE_DIF_CQI_MAX_BITS 3
|
||||
#define SRSLTE_PMI_MAX_BITS 4
|
||||
|
||||
typedef struct {
|
||||
bool configured;
|
||||
uint32_t pmi_idx;
|
||||
uint32_t ri_idx;
|
||||
bool ri_idx_present;
|
||||
bool simul_cqi_ack;
|
||||
bool format_is_subband;
|
||||
uint32_t subband_size;
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#define SRSLTE_BCH_PAYLOADCRC_LEN (SRSLTE_BCH_PAYLOAD_LEN+16)
|
||||
#define SRSLTE_BCH_ENCODED_LEN 3*(SRSLTE_BCH_PAYLOADCRC_LEN)
|
||||
|
||||
#define SRSLTE_PBCH_MAX_RE 256 // make it avx2-aligned
|
||||
|
||||
/* PBCH object */
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_cell_t cell;
|
||||
|
@ -83,12 +85,14 @@ typedef struct SRSLTE_API {
|
|||
|
||||
} srslte_pbch_t;
|
||||
|
||||
SRSLTE_API int srslte_pbch_init(srslte_pbch_t *q,
|
||||
srslte_cell_t cell);
|
||||
SRSLTE_API int srslte_pbch_init(srslte_pbch_t *q);
|
||||
|
||||
SRSLTE_API void srslte_pbch_free(srslte_pbch_t *q);
|
||||
|
||||
SRSLTE_API int srslte_pbch_decode(srslte_pbch_t *q,
|
||||
SRSLTE_API int srslte_pbch_set_cell(srslte_pbch_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pbch_decode(srslte_pbch_t *q,
|
||||
cf_t *slot1_symbols,
|
||||
cf_t *ce_slot1[SRSLTE_MAX_PORTS],
|
||||
float noise_estimate,
|
||||
|
|
|
@ -78,14 +78,12 @@ typedef struct SRSLTE_API {
|
|||
|
||||
} srslte_pcfich_t;
|
||||
|
||||
SRSLTE_API int srslte_pcfich_init(srslte_pcfich_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
SRSLTE_API int srslte_pcfich_init(srslte_pcfich_t *q,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_pcfich_init_multi(srslte_pcfich_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas);
|
||||
SRSLTE_API int srslte_pcfich_set_cell(srslte_pcfich_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_pcfich_free(srslte_pcfich_t *q);
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef struct SRSLTE_API {
|
|||
uint32_t nof_cce;
|
||||
uint32_t max_bits;
|
||||
uint32_t nof_rx_antennas;
|
||||
bool is_ue;
|
||||
|
||||
srslte_regs_t *regs;
|
||||
|
||||
|
@ -84,29 +85,16 @@ typedef struct SRSLTE_API {
|
|||
|
||||
} srslte_pdcch_t;
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
SRSLTE_API int srslte_pdcch_init_ue(srslte_pdcch_t *q,
|
||||
uint32_t max_prb,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init_tx(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
SRSLTE_API int srslte_pdcch_init_enb(srslte_pdcch_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init_rx(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init_multi(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init_txrx(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas,
|
||||
bool isReceiver);
|
||||
SRSLTE_API int srslte_pdcch_set_cell(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q);
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
typedef struct {
|
||||
srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
uint32_t cell_id;
|
||||
bool sequence_generated;
|
||||
} srslte_pdsch_user_t;
|
||||
|
||||
|
@ -57,9 +58,13 @@ typedef struct SRSLTE_API {
|
|||
srslte_cell_t cell;
|
||||
|
||||
uint32_t nof_rx_antennas;
|
||||
|
||||
uint32_t last_nof_iterations[SRSLTE_MAX_CODEWORDS];
|
||||
|
||||
uint32_t max_re;
|
||||
|
||||
|
||||
uint16_t ue_rnti;
|
||||
bool is_ue;
|
||||
|
||||
/* buffers */
|
||||
// void buffers are shared for tx and rx
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
|
||||
|
@ -73,21 +78,27 @@ typedef struct SRSLTE_API {
|
|||
|
||||
// This is to generate the scrambling seq for multiple CRNTIs
|
||||
srslte_pdsch_user_t **users;
|
||||
|
||||
|
||||
srslte_sequence_t tmp_seq;
|
||||
|
||||
srslte_sch_t dl_sch;
|
||||
|
||||
} srslte_pdsch_t;
|
||||
|
||||
SRSLTE_API int srslte_pdsch_init_tx(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_init_rx(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_antennas);
|
||||
SRSLTE_API int srslte_pdsch_init_ue(srslte_pdsch_t *q,
|
||||
uint32_t max_prb,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_init_enb(srslte_pdsch_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
|
||||
SRSLTE_API int srslte_pdsch_set_cell(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
|
||||
uint16_t rnti);
|
||||
|
||||
SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q,
|
||||
|
@ -139,10 +150,12 @@ SRSLTE_API int srslte_pdsch_cn_compute(srslte_pdsch_t *q,
|
|||
uint32_t nof_ce,
|
||||
float *cn);
|
||||
|
||||
SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, uint32_t max_iter);
|
||||
SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q,
|
||||
uint32_t max_iter);
|
||||
|
||||
SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q);
|
||||
SRSLTE_API float srslte_pdsch_last_noi(srslte_pdsch_t *q);
|
||||
|
||||
SRSLTE_API uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q);
|
||||
SRSLTE_API uint32_t srslte_pdsch_last_noi_cw(srslte_pdsch_t *q,
|
||||
uint32_t cw_idx);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -85,26 +85,24 @@ typedef struct SRSLTE_API {
|
|||
|
||||
} srslte_phich_t;
|
||||
|
||||
SRSLTE_API int srslte_phich_init(srslte_phich_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_phich_init_multi(srslte_phich_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas);
|
||||
SRSLTE_API int srslte_phich_init(srslte_phich_t *q,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API void srslte_phich_free(srslte_phich_t *q);
|
||||
|
||||
SRSLTE_API void srslte_phich_calc(srslte_phich_t *q,
|
||||
SRSLTE_API int srslte_phich_set_cell(srslte_phich_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_phich_calc(srslte_phich_t *q,
|
||||
uint32_t n_prb_lowest,
|
||||
uint32_t n_dmrs,
|
||||
uint32_t *ngroup,
|
||||
uint32_t *nseq);
|
||||
|
||||
SRSLTE_API int srslte_phich_decode(srslte_phich_t *q,
|
||||
cf_t *slot_symbols,
|
||||
cf_t *ce[SRSLTE_MAX_PORTS],
|
||||
cf_t *slot_symbols[SRSLTE_MAX_PORTS],
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
float noise_estimate,
|
||||
uint32_t ngroup,
|
||||
uint32_t nseq,
|
||||
|
@ -112,16 +110,6 @@ SRSLTE_API int srslte_phich_decode(srslte_phich_t *q,
|
|||
uint8_t *ack,
|
||||
float *distance);
|
||||
|
||||
SRSLTE_API int srslte_phich_decode_multi(srslte_phich_t *q,
|
||||
cf_t *slot_symbols[SRSLTE_MAX_PORTS],
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
float noise_estimate,
|
||||
uint32_t ngroup,
|
||||
uint32_t nseq,
|
||||
uint32_t nsubframe,
|
||||
uint8_t *ack,
|
||||
float *distance);
|
||||
|
||||
SRSLTE_API int srslte_phich_encode(srslte_phich_t *q,
|
||||
uint8_t ack,
|
||||
uint32_t ngroup,
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2015 Software Radio Systems Limited
|
||||
*
|
||||
* \section LICENSE
|
||||
*
|
||||
* This file is part of the srsLTE library.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE 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 Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero 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/.
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* File: pmch.h
|
||||
*
|
||||
* Description: Physical multicast channel
|
||||
*
|
||||
* Reference: 3GPP TS 36.211 version 10.0.0 Release 10 Sec. 6.5
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef PMCH_
|
||||
#define PMCH_
|
||||
|
||||
#include "srslte/config.h"
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
#include "srslte/phy/mimo/precoding.h"
|
||||
#include "srslte/phy/mimo/layermap.h"
|
||||
#include "srslte/phy/modem/mod.h"
|
||||
#include "srslte/phy/modem/demod_soft.h"
|
||||
#include "srslte/phy/scrambling/scrambling.h"
|
||||
#include "srslte/phy/phch/dci.h"
|
||||
#include "srslte/phy/phch/regs.h"
|
||||
#include "srslte/phy/phch/sch.h"
|
||||
#include "srslte/phy/common/sequence.h"
|
||||
|
||||
typedef struct {
|
||||
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
} srslte_pmch_seq_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_cbsegm_t cb_segm;
|
||||
srslte_ra_dl_grant_t grant;
|
||||
srslte_ra_nbits_t nbits[SRSLTE_MAX_CODEWORDS];
|
||||
uint32_t sf_idx;
|
||||
} srslte_pmch_cfg_t;
|
||||
|
||||
/* PMCH object */
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_cell_t cell;
|
||||
|
||||
uint32_t nof_rx_antennas;
|
||||
|
||||
uint32_t max_re;
|
||||
|
||||
/* buffers */
|
||||
// void buffers are shared for tx and rx
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
cf_t *symbols[SRSLTE_MAX_PORTS];
|
||||
cf_t *x[SRSLTE_MAX_PORTS];
|
||||
cf_t *d;
|
||||
void *e;
|
||||
|
||||
/* tx & rx objects */
|
||||
srslte_modem_table_t mod[4];
|
||||
|
||||
// This is to generate the scrambling seq for multiple MBSFN Area IDs
|
||||
srslte_pmch_seq_t **seqs;
|
||||
|
||||
srslte_sch_t dl_sch;
|
||||
|
||||
} srslte_pmch_t;
|
||||
|
||||
|
||||
SRSLTE_API int srslte_pmch_init(srslte_pmch_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API int srslte_pmch_init_multi(srslte_pmch_t *q,
|
||||
uint32_t max_prb,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API void srslte_pmch_free(srslte_pmch_t *q);
|
||||
|
||||
|
||||
|
||||
SRSLTE_API int srslte_pmch_set_area_id(srslte_pmch_t *q, uint16_t area_id);
|
||||
|
||||
SRSLTE_API void srslte_pmch_free_area_id(srslte_pmch_t *q, uint16_t area_id);
|
||||
|
||||
|
||||
|
||||
SRSLTE_API int srslte_pmch_get(srslte_pmch_t *q, cf_t *sf_symbols, cf_t *symbols, uint32_t lstart);
|
||||
|
||||
SRSLTE_API int srslte_pmch_put(srslte_pmch_t *q, cf_t *symbols, cf_t *sf_symbols, uint32_t lstart);
|
||||
|
||||
SRSLTE_API int srslte_pmch_cp(srslte_pmch_t *q, cf_t *input, cf_t *output, uint32_t lstart_grant, bool put);
|
||||
|
||||
|
||||
|
||||
SRSLTE_API float srslte_pmch_coderate(uint32_t tbs,
|
||||
uint32_t nof_re);
|
||||
|
||||
|
||||
SRSLTE_API int srslte_pmch_cfg(srslte_pdsch_cfg_t *cfg,
|
||||
srslte_cell_t cell,
|
||||
srslte_ra_dl_grant_t *grant,
|
||||
uint32_t cfi,
|
||||
uint32_t sf_idx);
|
||||
|
||||
SRSLTE_API int srslte_pmch_encode(srslte_pmch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_tx_t *softbuffer,
|
||||
uint8_t *data,
|
||||
uint16_t area_id,
|
||||
cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
|
||||
|
||||
SRSLTE_API int srslte_pmch_decode(srslte_pmch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_rx_t *softbuffer,
|
||||
cf_t *sf_symbols,
|
||||
cf_t *ce[SRSLTE_MAX_PORTS],
|
||||
float noise_estimate,
|
||||
uint16_t area_id,
|
||||
uint8_t *data);
|
||||
|
||||
SRSLTE_API int srslte_pmch_decode_multi(srslte_pmch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_rx_t *softbuffer,
|
||||
cf_t *sf_symbols[SRSLTE_MAX_PORTS],
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
float noise_estimate,
|
||||
uint16_t area_id,
|
||||
uint8_t *data);
|
||||
|
||||
SRSLTE_API float srslte_pmch_average_noi(srslte_pmch_t *q);
|
||||
|
||||
SRSLTE_API uint32_t srslte_pmch_last_noi(srslte_pmch_t *q);
|
||||
|
||||
#endif
|
|
@ -44,6 +44,8 @@
|
|||
#include "srslte/phy/common/phy_common.h"
|
||||
|
||||
|
||||
#define SRSLTE_PRACH_MAX_LEN (2*24576+21024) // Maximum Tcp + Tseq
|
||||
|
||||
/** Generation and detection of RACH signals for uplink.
|
||||
* Currently only supports preamble formats 0-3.
|
||||
* Does not currently support high speed flag.
|
||||
|
@ -60,6 +62,8 @@ typedef struct SRSLTE_API {
|
|||
uint32_t N_ifft_ul; // IFFT size for uplink
|
||||
uint32_t N_ifft_prach; // IFFT size for PRACH generation
|
||||
|
||||
uint32_t max_N_ifft_ul;
|
||||
|
||||
// Working parameters
|
||||
uint32_t N_zc; // PRACH sequence length
|
||||
uint32_t N_cs; // Cyclic shift size
|
||||
|
@ -82,12 +86,12 @@ typedef struct SRSLTE_API {
|
|||
float *corr;
|
||||
|
||||
// PRACH IFFT
|
||||
srslte_dft_plan_t *fft;
|
||||
srslte_dft_plan_t *ifft;
|
||||
srslte_dft_plan_t fft;
|
||||
srslte_dft_plan_t ifft;
|
||||
|
||||
// ZC-sequence FFT and IFFT
|
||||
srslte_dft_plan_t *zc_fft;
|
||||
srslte_dft_plan_t *zc_ifft;
|
||||
srslte_dft_plan_t zc_fft;
|
||||
srslte_dft_plan_t zc_ifft;
|
||||
|
||||
cf_t *signal_fft;
|
||||
float detect_factor;
|
||||
|
@ -129,11 +133,14 @@ SRSLTE_API void srslte_prach_sf_config(uint32_t config_idx,
|
|||
srslte_prach_sf_config_t *sf_config);
|
||||
|
||||
SRSLTE_API int srslte_prach_init(srslte_prach_t *p,
|
||||
uint32_t N_ifft_ul,
|
||||
uint32_t config_idx,
|
||||
uint32_t root_seq_index,
|
||||
bool high_speed_flag,
|
||||
uint32_t zero_corr_zone_config);
|
||||
uint32_t max_N_ifft_ul);
|
||||
|
||||
SRSLTE_API int srslte_prach_set_cell(srslte_prach_t *p,
|
||||
uint32_t N_ifft_ul,
|
||||
uint32_t config_idx,
|
||||
uint32_t root_seq_index,
|
||||
bool high_speed_flag,
|
||||
uint32_t zero_corr_zone_config);
|
||||
|
||||
SRSLTE_API int srslte_prach_init_cfg(srslte_prach_t* p,
|
||||
srslte_prach_cfg_t* cfg,
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#define SRSLTE_PUCCH_N_SEQ 12
|
||||
#define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B
|
||||
#define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS
|
||||
#define SRSLTE_PUCCH_MAX_SYMBOLS 120
|
||||
#define SRSLTE_PUCCH_MAX_SYMBOLS 128
|
||||
|
||||
typedef enum SRSLTE_API {
|
||||
SRSLTE_PUCCH_FORMAT_1 = 0,
|
||||
|
@ -115,12 +115,14 @@ typedef struct SRSLTE_API {
|
|||
}srslte_pucch_t;
|
||||
|
||||
|
||||
SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q,
|
||||
srslte_cell_t cell);
|
||||
SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q);
|
||||
|
||||
SRSLTE_API void srslte_pucch_free(srslte_pucch_t *q);
|
||||
|
||||
SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q,
|
||||
SRSLTE_API int srslte_pucch_set_cell(srslte_pucch_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q,
|
||||
srslte_pucch_cfg_t* cfg,
|
||||
bool group_hopping_en);
|
||||
|
||||
|
|
|
@ -62,13 +62,16 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
bool sequences_generated;
|
||||
} srslte_pusch_user_t;
|
||||
uint32_t cell_id;
|
||||
bool sequence_generated;
|
||||
} srslte_pusch_user_t;
|
||||
|
||||
/* PUSCH object */
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_cell_t cell;
|
||||
|
||||
bool is_ue;
|
||||
uint16_t ue_rnti;
|
||||
uint32_t max_re;
|
||||
|
||||
srslte_dft_precoding_t dft_precoding;
|
||||
|
@ -96,12 +99,18 @@ typedef struct SRSLTE_API {
|
|||
}srslte_pusch_t;
|
||||
|
||||
|
||||
SRSLTE_API int srslte_pusch_init(srslte_pusch_t *q,
|
||||
srslte_cell_t cell);
|
||||
SRSLTE_API int srslte_pusch_init_ue(srslte_pusch_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API int srslte_pusch_init_enb(srslte_pusch_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_pusch_free(srslte_pusch_t *q);
|
||||
|
||||
SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
|
||||
SRSLTE_API int srslte_pusch_set_cell(srslte_pusch_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
|
||||
srslte_pusch_cfg_t *cfg,
|
||||
srslte_ra_ul_grant_t *grant,
|
||||
srslte_uci_cfg_t *uci_cfg,
|
||||
|
@ -114,7 +123,7 @@ SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
|
|||
SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q,
|
||||
uint16_t rnti);
|
||||
|
||||
SRSLTE_API void srslte_pusch_clear_rnti(srslte_pusch_t *q,
|
||||
SRSLTE_API void srslte_pusch_free_rnti(srslte_pusch_t *q,
|
||||
uint16_t rnti);
|
||||
|
||||
SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q,
|
||||
|
|
|
@ -103,11 +103,17 @@ typedef struct SRSLTE_API {
|
|||
bool prb_idx[2][SRSLTE_MAX_PRB];
|
||||
uint32_t nof_prb;
|
||||
uint32_t Qm[SRSLTE_MAX_CODEWORDS];
|
||||
uint32_t Qm2[SRSLTE_MAX_CODEWORDS];
|
||||
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
|
||||
srslte_ra_mcs_t mcs2[SRSLTE_MAX_CODEWORDS];
|
||||
uint32_t nof_tb;
|
||||
srslte_sf_t sf_type;
|
||||
bool tb_en[SRSLTE_MAX_CODEWORDS];
|
||||
uint32_t pinfo;
|
||||
} srslte_ra_dl_grant_t;
|
||||
|
||||
#define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0))
|
||||
|
||||
/** Unpacked DCI message for DL grant */
|
||||
typedef struct SRSLTE_API {
|
||||
|
||||
|
@ -288,4 +294,9 @@ SRSLTE_API void srslte_ra_pusch_fprint(FILE *f,
|
|||
SRSLTE_API void srslte_ra_ul_grant_fprint(FILE *f,
|
||||
srslte_ra_ul_grant_t *grant);
|
||||
|
||||
SRSLTE_API int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb);
|
||||
|
||||
SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb);
|
||||
|
||||
|
||||
#endif /* RB_ALLOC_H_ */
|
||||
|
|
|
@ -56,10 +56,9 @@
|
|||
/* DL-SCH AND UL-SCH common functions */
|
||||
typedef struct SRSLTE_API {
|
||||
|
||||
uint32_t max_iterations;
|
||||
uint32_t nof_iterations;
|
||||
float average_nof_iterations;
|
||||
|
||||
uint32_t max_iterations;
|
||||
uint32_t nof_iterations;
|
||||
|
||||
/* buffers */
|
||||
uint8_t *cb_in;
|
||||
uint8_t *parity_bits;
|
||||
|
@ -77,6 +76,7 @@ typedef struct SRSLTE_API {
|
|||
srslte_uci_cqi_pusch_t uci_cqi;
|
||||
|
||||
} srslte_sch_t;
|
||||
#include "srslte/phy/phch/pmch.h"
|
||||
|
||||
SRSLTE_API int srslte_sch_init(srslte_sch_t *q);
|
||||
|
||||
|
@ -86,8 +86,6 @@ SRSLTE_API void srslte_sch_free(srslte_sch_t *q);
|
|||
SRSLTE_API void srslte_sch_set_max_noi(srslte_sch_t *q,
|
||||
uint32_t max_iterations);
|
||||
|
||||
SRSLTE_API float srslte_sch_average_noi(srslte_sch_t *q);
|
||||
|
||||
SRSLTE_API uint32_t srslte_sch_last_noi(srslte_sch_t *q);
|
||||
|
||||
SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q,
|
||||
|
|
|
@ -64,6 +64,10 @@ typedef struct SRSLTE_API {
|
|||
typedef struct SRSLTE_API {
|
||||
uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS];
|
||||
uint32_t uci_cqi_len;
|
||||
uint8_t uci_dif_cqi[SRSLTE_DIF_CQI_MAX_BITS];
|
||||
uint32_t uci_dif_cqi_len;
|
||||
uint8_t uci_pmi[SRSLTE_PMI_MAX_BITS];
|
||||
uint8_t uci_pmi_len;
|
||||
uint8_t uci_ri; // Only 1-bit supported for RI
|
||||
uint32_t uci_ri_len;
|
||||
uint8_t uci_ack; // 1st codeword bit for HARQ-ACK
|
||||
|
@ -119,8 +123,9 @@ SRSLTE_API int srslte_uci_decode_cqi_pusch(srslte_uci_cqi_pusch_t *q,
|
|||
bool *cqi_ack);
|
||||
|
||||
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
|
||||
uint8_t data,
|
||||
uint32_t O_cqi,
|
||||
uint8_t acks[2],
|
||||
uint32_t nof_acks,
|
||||
uint32_t O_cqi,
|
||||
float beta,
|
||||
uint32_t H_prime_total,
|
||||
srslte_uci_bit_t *ri_bits);
|
||||
|
@ -132,7 +137,8 @@ SRSLTE_API int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg,
|
|||
uint32_t H_prime_total,
|
||||
uint32_t O_cqi,
|
||||
srslte_uci_bit_t *ack_bits,
|
||||
uint8_t *data);
|
||||
uint8_t acks[2],
|
||||
uint32_t nof_acks);
|
||||
|
||||
SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
|
||||
uint8_t data,
|
||||
|
|
|
@ -67,7 +67,8 @@ SRSLTE_API void srslte_interp_linear_f(float *input,
|
|||
|
||||
typedef struct {
|
||||
cf_t *diff_vec;
|
||||
uint32_t vector_len;
|
||||
uint32_t vector_len;
|
||||
uint32_t max_vector_len;
|
||||
} srslte_interp_linsrslte_vec_t;
|
||||
|
||||
SRSLTE_API int srslte_interp_linear_vector_init(srslte_interp_linsrslte_vec_t *q,
|
||||
|
@ -75,6 +76,9 @@ SRSLTE_API int srslte_interp_linear_vector_init(srslte_interp_linsrslte_vec_t *q
|
|||
|
||||
SRSLTE_API void srslte_interp_linear_vector_free(srslte_interp_linsrslte_vec_t *q);
|
||||
|
||||
SRSLTE_API int srslte_interp_linear_vector_resize(srslte_interp_linsrslte_vec_t *q,
|
||||
uint32_t vector_len);
|
||||
|
||||
SRSLTE_API void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q,
|
||||
cf_t *in0,
|
||||
cf_t *in1,
|
||||
|
@ -107,7 +111,9 @@ typedef struct {
|
|||
cf_t *diff_vec2;
|
||||
float *ramp;
|
||||
uint32_t vector_len;
|
||||
uint32_t M;
|
||||
uint32_t M;
|
||||
uint32_t max_vector_len;
|
||||
uint32_t max_M;
|
||||
} srslte_interp_lin_t;
|
||||
|
||||
SRSLTE_API int srslte_interp_linear_init(srslte_interp_lin_t *q,
|
||||
|
@ -116,6 +122,10 @@ SRSLTE_API int srslte_interp_linear_init(srslte_interp_lin_t *q,
|
|||
|
||||
SRSLTE_API void srslte_interp_linear_free(srslte_interp_lin_t *q);
|
||||
|
||||
SRSLTE_API int srslte_interp_linear_resize(srslte_interp_lin_t *q,
|
||||
uint32_t vector_len,
|
||||
uint32_t M);
|
||||
|
||||
SRSLTE_API void srslte_interp_linear_offset(srslte_interp_lin_t *q,
|
||||
cf_t *input,
|
||||
cf_t *output,
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef struct SRSLTE_API {
|
|||
float last_freq;
|
||||
float tol;
|
||||
int nsamples;
|
||||
int max_samples;
|
||||
srslte_cexptab_t tab;
|
||||
cf_t *cur_cexp;
|
||||
}srslte_cfo_t;
|
||||
|
@ -58,8 +59,8 @@ SRSLTE_API int srslte_cfo_init(srslte_cfo_t *h,
|
|||
|
||||
SRSLTE_API void srslte_cfo_free(srslte_cfo_t *h);
|
||||
|
||||
SRSLTE_API int srslte_cfo_realloc(srslte_cfo_t *h,
|
||||
uint32_t samples);
|
||||
SRSLTE_API int srslte_cfo_resize(srslte_cfo_t *h,
|
||||
uint32_t samples);
|
||||
|
||||
SRSLTE_API void srslte_cfo_set_tol(srslte_cfo_t *h,
|
||||
float tol);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
typedef struct {
|
||||
cf_t *corr;
|
||||
uint32_t symbol_sz;
|
||||
uint32_t max_symbol_sz;
|
||||
} srslte_cp_synch_t;
|
||||
|
||||
SRSLTE_API int srslte_cp_synch_init(srslte_cp_synch_t *q,
|
||||
|
@ -42,6 +43,9 @@ SRSLTE_API int srslte_cp_synch_init(srslte_cp_synch_t *q,
|
|||
|
||||
SRSLTE_API void srslte_cp_synch_free(srslte_cp_synch_t *q);
|
||||
|
||||
SRSLTE_API int srslte_cp_synch_resize(srslte_cp_synch_t *q,
|
||||
uint32_t symbol_sz);
|
||||
|
||||
SRSLTE_API uint32_t srslte_cp_synch(srslte_cp_synch_t *q,
|
||||
cf_t *input,
|
||||
uint32_t max_offset,
|
||||
|
|
|
@ -79,6 +79,10 @@ typedef struct SRSLTE_API {
|
|||
|
||||
#endif
|
||||
int decimate;
|
||||
|
||||
uint32_t max_frame_size;
|
||||
uint32_t max_fft_size;
|
||||
|
||||
uint32_t frame_size;
|
||||
uint32_t N_id_2;
|
||||
uint32_t fft_size;
|
||||
|
@ -113,6 +117,10 @@ SRSLTE_API int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q,
|
|||
int cfo_i,
|
||||
int decimate);
|
||||
|
||||
SRSLTE_API int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size,
|
||||
uint32_t fft_size,
|
||||
int offset);
|
||||
|
||||
SRSLTE_API int srslte_pss_synch_init(srslte_pss_synch_t *q,
|
||||
uint32_t frame_size);
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ typedef struct SRSLTE_API {
|
|||
srslte_dft_plan_t dftp_input;
|
||||
|
||||
uint32_t fft_size;
|
||||
uint32_t max_fft_size;
|
||||
|
||||
float corr_peak_threshold;
|
||||
uint32_t symbol_sz;
|
||||
|
@ -89,7 +90,7 @@ typedef struct SRSLTE_API {
|
|||
SRSLTE_API int srslte_sss_synch_init(srslte_sss_synch_t *q,
|
||||
uint32_t fft_size);
|
||||
|
||||
SRSLTE_API int srslte_sss_synch_realloc(srslte_sss_synch_t *q,
|
||||
SRSLTE_API int srslte_sss_synch_resize(srslte_sss_synch_t *q,
|
||||
uint32_t fft_size);
|
||||
|
||||
SRSLTE_API void srslte_sss_synch_free(srslte_sss_synch_t *q);
|
||||
|
|
|
@ -75,6 +75,8 @@ typedef struct SRSLTE_API {
|
|||
uint32_t frame_size;
|
||||
uint32_t max_offset;
|
||||
bool enable_cfo_corr;
|
||||
bool mean_cfo2_isunset;
|
||||
bool mean_cfo_isunset;
|
||||
float mean_cfo;
|
||||
float mean_cfo2;
|
||||
int cfo_i;
|
||||
|
@ -85,6 +87,7 @@ typedef struct SRSLTE_API {
|
|||
uint32_t cp_len;
|
||||
srslte_cfo_t cfocorr;
|
||||
srslte_cfo_t cfocorr2;
|
||||
float current_cfo_tol;
|
||||
sss_alg_t sss_alg;
|
||||
bool detect_cp;
|
||||
bool sss_en;
|
||||
|
@ -97,6 +100,8 @@ typedef struct SRSLTE_API {
|
|||
float M_ext_avg;
|
||||
cf_t *temp;
|
||||
|
||||
uint32_t max_frame_size;
|
||||
|
||||
}srslte_sync_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -121,6 +126,11 @@ SRSLTE_API int srslte_sync_init_decim(srslte_sync_t *q,
|
|||
|
||||
SRSLTE_API void srslte_sync_free(srslte_sync_t *q);
|
||||
|
||||
SRSLTE_API int srslte_sync_resize(srslte_sync_t *q,
|
||||
uint32_t frame_size,
|
||||
uint32_t max_offset,
|
||||
uint32_t fft_size);
|
||||
|
||||
SRSLTE_API void srslte_sync_reset(srslte_sync_t *q);
|
||||
|
||||
/* Finds a correlation peak in the input signal around position find_offset */
|
||||
|
@ -138,6 +148,9 @@ SRSLTE_API srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q,
|
|||
SRSLTE_API void srslte_sync_set_threshold(srslte_sync_t *q,
|
||||
float threshold);
|
||||
|
||||
SRSLTE_API void srslte_sync_set_cfo_tol(srslte_sync_t *q,
|
||||
float tol);
|
||||
|
||||
/* Gets the subframe idx (0 or 5) */
|
||||
SRSLTE_API uint32_t srslte_sync_get_sf_idx(srslte_sync_t *q);
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "srslte/phy/phch/pcfich.h"
|
||||
#include "srslte/phy/phch/pdcch.h"
|
||||
#include "srslte/phy/phch/pdsch.h"
|
||||
#include "srslte/phy/phch/pmch.h"
|
||||
#include "srslte/phy/phch/pdsch_cfg.h"
|
||||
#include "srslte/phy/phch/phich.h"
|
||||
#include "srslte/phy/phch/ra.h"
|
||||
|
@ -76,14 +77,17 @@ typedef struct SRSLTE_API {
|
|||
srslte_pcfich_t pcfich;
|
||||
srslte_pdcch_t pdcch;
|
||||
srslte_pdsch_t pdsch;
|
||||
srslte_pmch_t pmch;
|
||||
srslte_phich_t phich;
|
||||
srslte_regs_t regs;
|
||||
srslte_ofdm_t fft;
|
||||
srslte_ofdm_t fft_mbsfn;
|
||||
srslte_chest_dl_t chest;
|
||||
|
||||
srslte_cfo_t sfo_correct;
|
||||
|
||||
srslte_pdsch_cfg_t pdsch_cfg;
|
||||
srslte_pdsch_cfg_t pdsch_cfg;
|
||||
srslte_pdsch_cfg_t pmch_cfg;
|
||||
srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
|
||||
srslte_ra_dl_dci_t dl_dci;
|
||||
srslte_cell_t cell;
|
||||
|
@ -103,9 +107,14 @@ typedef struct SRSLTE_API {
|
|||
srslte_dci_format_t dci_format;
|
||||
uint64_t pkt_errors;
|
||||
uint64_t pkts_total;
|
||||
uint64_t pdsch_pkt_errors;
|
||||
uint64_t pdsch_pkts_total;
|
||||
uint64_t pmch_pkt_errors;
|
||||
uint64_t pmch_pkts_total;
|
||||
uint64_t nof_detected;
|
||||
|
||||
uint16_t current_rnti;
|
||||
uint16_t current_mbsfn_area_id;
|
||||
dci_blind_search_t current_ss_ue[3][10];
|
||||
dci_blind_search_t current_ss_common[3];
|
||||
srslte_dci_location_t last_location;
|
||||
|
@ -119,19 +128,34 @@ typedef struct SRSLTE_API {
|
|||
|
||||
/* This function shall be called just after the initial synchronization */
|
||||
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
|
||||
srslte_cell_t cell,
|
||||
uint32_t max_prb,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
|
||||
cf_t *input[SRSLTE_MAX_PORTS],
|
||||
uint32_t sf_idx,
|
||||
uint32_t *cfi);
|
||||
SRSLTE_API int srslte_ue_dl_set_cell(srslte_ue_dl_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q,
|
||||
int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
|
||||
cf_t *input[SRSLTE_MAX_PORTS],
|
||||
uint32_t sf_idx,
|
||||
uint32_t *cfi);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q,
|
||||
cf_t *input[SRSLTE_MAX_PORTS],
|
||||
uint32_t sf_idx,
|
||||
uint32_t *cfi,
|
||||
srslte_sf_t sf_type);
|
||||
|
||||
|
||||
int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q,
|
||||
uint32_t sf_idx,
|
||||
uint32_t *cfi);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_decode_estimate_mbsfn(srslte_ue_dl_t *q,
|
||||
uint32_t sf_idx,
|
||||
uint32_t *cfi);
|
||||
uint32_t *cfi,
|
||||
srslte_sf_t sf_type);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
|
||||
srslte_ra_dl_grant_t *grant,
|
||||
|
@ -181,13 +205,25 @@ SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q,
|
|||
uint16_t rnti,
|
||||
bool acks[SRSLTE_MAX_CODEWORDS]);
|
||||
|
||||
/* Used by example applications - full PMCH decode for a given MBSFN area ID
|
||||
* srslte_ue_dl_decode_fft_estimate_multi,
|
||||
* srslte_chest_dl_get_noise_estimate,
|
||||
* srslte_ue_dl_cfg_grant,
|
||||
* srslte_pmch_decode_multi
|
||||
*/
|
||||
SRSLTE_API int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q,
|
||||
cf_t *input[SRSLTE_MAX_PORTS],
|
||||
uint8_t *data,
|
||||
uint32_t tti);
|
||||
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q,
|
||||
uint32_t *ri,
|
||||
uint32_t *pmi,
|
||||
uint8_t *ri,
|
||||
uint8_t *pmi,
|
||||
float *current_sinr);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q,
|
||||
uint32_t *ri,
|
||||
uint8_t *ri,
|
||||
float *cn);
|
||||
|
||||
SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q,
|
||||
|
@ -200,6 +236,15 @@ SRSLTE_API void srslte_ue_dl_reset(srslte_ue_dl_t *q);
|
|||
SRSLTE_API void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q,
|
||||
uint16_t rnti);
|
||||
|
||||
/* Generate signals if required, store in q->current_mbsfn_area_id */
|
||||
SRSLTE_API int srslte_ue_dl_set_mbsfn_area_id(srslte_ue_dl_t *q,
|
||||
uint16_t mbsfn_area_id);
|
||||
|
||||
SRSLTE_API void srslte_ue_dl_set_non_mbsfn_region(srslte_ue_dl_t *q,
|
||||
uint8_t non_mbsfn_region_length);
|
||||
|
||||
|
||||
|
||||
SRSLTE_API void srslte_ue_dl_save_signal(srslte_ue_dl_t *q,
|
||||
srslte_softbuffer_rx_t *softbuffer,
|
||||
uint32_t tti,
|
||||
|
|
|
@ -79,10 +79,13 @@ typedef struct SRSLTE_API {
|
|||
} srslte_ue_mib_t;
|
||||
|
||||
SRSLTE_API int srslte_ue_mib_init(srslte_ue_mib_t *q,
|
||||
srslte_cell_t cell);
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_ue_mib_free(srslte_ue_mib_t *q);
|
||||
|
||||
SRSLTE_API int srslte_ue_mib_set_cell(srslte_ue_mib_t * q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_ue_mib_reset(srslte_ue_mib_t * q);
|
||||
|
||||
SRSLTE_API int srslte_ue_mib_decode(srslte_ue_mib_t * q,
|
||||
|
@ -104,21 +107,17 @@ typedef struct {
|
|||
uint32_t nof_rx_antennas;
|
||||
} srslte_ue_mib_sync_t;
|
||||
|
||||
SRSLTE_API int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
|
||||
uint32_t cell_id,
|
||||
srslte_cp_t cp,
|
||||
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t *),
|
||||
void *stream_handler);
|
||||
|
||||
SRSLTE_API int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
|
||||
uint32_t cell_id,
|
||||
srslte_cp_t cp,
|
||||
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t *),
|
||||
SRSLTE_API int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
|
||||
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t *),
|
||||
uint32_t nof_rx_antennas,
|
||||
void *stream_handler);
|
||||
|
||||
SRSLTE_API void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q);
|
||||
|
||||
SRSLTE_API int srslte_ue_mib_sync_set_cell(srslte_ue_mib_sync_t *q,
|
||||
uint32_t cell_id,
|
||||
srslte_cp_t cp);
|
||||
|
||||
SRSLTE_API void srslte_ue_mib_sync_reset(srslte_ue_mib_sync_t * q);
|
||||
|
||||
SRSLTE_API int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
|
||||
|
|
|
@ -69,6 +69,8 @@ typedef enum SRSLTE_API { SF_FIND, SF_TRACK} srslte_ue_sync_state_t;
|
|||
typedef struct SRSLTE_API {
|
||||
srslte_sync_t sfind;
|
||||
srslte_sync_t strack;
|
||||
|
||||
uint32_t max_prb;
|
||||
|
||||
srslte_agc_t agc;
|
||||
bool do_agc;
|
||||
|
@ -125,22 +127,25 @@ typedef struct SRSLTE_API {
|
|||
} srslte_ue_sync_t;
|
||||
|
||||
SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q,
|
||||
srslte_cell_t cell,
|
||||
uint32_t max_prb,
|
||||
bool search_cell,
|
||||
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*),
|
||||
void *stream_handler);
|
||||
|
||||
SRSLTE_API int srslte_ue_sync_init_multi(srslte_ue_sync_t *q,
|
||||
srslte_cell_t cell,
|
||||
SRSLTE_API int srslte_ue_sync_init_multi(srslte_ue_sync_t *q,
|
||||
uint32_t max_prb,
|
||||
bool search_cell,
|
||||
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
|
||||
uint32_t nof_rx_antennas,
|
||||
void *stream_handler);
|
||||
|
||||
SRSLTE_API int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
|
||||
srslte_cell_t cell,
|
||||
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
|
||||
uint32_t nof_rx_antennas,
|
||||
void *stream_handler,
|
||||
int decimate);
|
||||
SRSLTE_API int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
|
||||
uint32_t max_prb,
|
||||
bool search_cell,
|
||||
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
|
||||
uint32_t nof_rx_antennas,
|
||||
void *stream_handler,
|
||||
int decimate);
|
||||
|
||||
SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q,
|
||||
uint32_t nof_prb,
|
||||
|
@ -157,6 +162,9 @@ SRSLTE_API int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q,
|
|||
|
||||
SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q);
|
||||
|
||||
SRSLTE_API int srslte_ue_sync_set_cell(srslte_ue_sync_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
|
||||
double (set_gain_callback)(void*, double),
|
||||
float init_gain_value);
|
||||
|
@ -173,6 +181,9 @@ SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q,
|
|||
SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q,
|
||||
cf_t *input_buffer[SRSLTE_MAX_PORTS]);
|
||||
|
||||
SRSLTE_API void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q,
|
||||
float tol);
|
||||
|
||||
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
|
||||
float cfo);
|
||||
|
||||
|
|
|
@ -75,7 +75,8 @@ typedef struct SRSLTE_API {
|
|||
|
||||
bool normalize_en;
|
||||
bool cfo_en;
|
||||
|
||||
|
||||
float current_cfo_tol;
|
||||
float current_cfo;
|
||||
srslte_pucch_format_t last_pucch_format;
|
||||
|
||||
|
@ -106,15 +107,21 @@ typedef struct SRSLTE_API {
|
|||
|
||||
|
||||
/* This function shall be called just after the initial synchronization */
|
||||
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
|
||||
srslte_cell_t cell);
|
||||
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
|
||||
uint32_t max_prb);
|
||||
|
||||
SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q);
|
||||
|
||||
SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q,
|
||||
SRSLTE_API int srslte_ue_ul_set_cell(srslte_ue_ul_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API void srslte_ue_ul_set_cfo_tol(srslte_ue_ul_t *q,
|
||||
float tol);
|
||||
|
||||
SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q,
|
||||
float cur_cfo);
|
||||
|
||||
SRSLTE_API void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q,
|
||||
SRSLTE_API void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q,
|
||||
bool enabled);
|
||||
|
||||
SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q,
|
||||
|
|
|
@ -46,6 +46,8 @@ typedef struct SRSLTE_API {
|
|||
uint32_t input_len;
|
||||
uint32_t filter_len;
|
||||
uint32_t output_len;
|
||||
uint32_t max_input_len;
|
||||
uint32_t max_filter_len;
|
||||
srslte_dft_plan_t input_plan;
|
||||
srslte_dft_plan_t filter_plan;
|
||||
srslte_dft_plan_t output_plan;
|
||||
|
@ -58,6 +60,9 @@ SRSLTE_API int srslte_conv_fft_cc_init(srslte_conv_fft_cc_t *q,
|
|||
uint32_t input_len,
|
||||
uint32_t filter_len);
|
||||
|
||||
SRSLTE_API int srslte_conv_fft_cc_replan(srslte_conv_fft_cc_t *q,
|
||||
uint32_t input_len,
|
||||
uint32_t filter_len);
|
||||
|
||||
SRSLTE_API void srslte_conv_fft_cc_free(srslte_conv_fft_cc_t *q);
|
||||
|
||||
|
|
|
@ -57,8 +57,7 @@ namespace srslte {
|
|||
bzero(&end_of_burst_time, sizeof(srslte_timestamp_t));
|
||||
bzero(zeros, burst_preamble_max_samples*sizeof(cf_t));
|
||||
|
||||
sf_len = 0;
|
||||
burst_preamble_sec = 0;
|
||||
burst_preamble_sec = 0;
|
||||
is_start_of_burst = false;
|
||||
burst_preamble_samples = 0;
|
||||
burst_preamble_time_rounded = 0;
|
||||
|
@ -72,13 +71,12 @@ namespace srslte {
|
|||
rx_freq = 0;
|
||||
trace_enabled = false;
|
||||
tti = 0;
|
||||
agc_enabled = false;
|
||||
offset = 0;
|
||||
|
||||
agc_enabled = false;
|
||||
};
|
||||
|
||||
bool init(char *args = NULL, char *devname = NULL);
|
||||
void stop();
|
||||
void stop();
|
||||
void reset();
|
||||
bool start_agc(bool tx_gain_same_rx);
|
||||
|
||||
void set_burst_preamble(double preamble_us);
|
||||
|
@ -98,15 +96,16 @@ namespace srslte {
|
|||
void set_tx_rx_gain_offset(float offset);
|
||||
double set_rx_gain_th(float gain);
|
||||
|
||||
void set_tx_freq(float freq);
|
||||
void set_rx_freq(float freq);
|
||||
void set_freq_offset(double freq);
|
||||
void set_tx_freq(double freq);
|
||||
void set_rx_freq(double freq);
|
||||
|
||||
float get_tx_freq();
|
||||
float get_rx_freq();
|
||||
double get_tx_freq();
|
||||
double get_rx_freq();
|
||||
|
||||
void set_master_clock_rate(float rate);
|
||||
void set_tx_srate(float srate);
|
||||
void set_rx_srate(float srate);
|
||||
void set_master_clock_rate(double rate);
|
||||
void set_tx_srate(double srate);
|
||||
void set_rx_srate(double srate);
|
||||
|
||||
float get_tx_gain();
|
||||
float get_rx_gain();
|
||||
|
@ -122,9 +121,8 @@ namespace srslte {
|
|||
void stop_rx();
|
||||
|
||||
void set_tti(uint32_t tti);
|
||||
void tx_offset(int offset);
|
||||
void set_tti_len(uint32_t sf_len);
|
||||
uint32_t get_tti_len();
|
||||
|
||||
bool is_first_of_burst();
|
||||
|
||||
void register_error_handler(srslte_rf_error_handler_t h);
|
||||
|
||||
|
@ -156,9 +154,9 @@ namespace srslte {
|
|||
|
||||
const static double blade_default_burst_preamble_sec = 0.0;
|
||||
const static double blade_default_tx_adv_samples = 27;
|
||||
const static double blade_default_tx_adv_offset_sec = 1e-6;
|
||||
|
||||
float tx_freq, rx_freq;
|
||||
const static double blade_default_tx_adv_offset_sec = 1e-6;
|
||||
|
||||
double tx_freq, rx_freq, freq_offset;
|
||||
|
||||
trace<uint32_t> tr_local_time;
|
||||
trace<uint32_t> tr_usrp_time;
|
||||
|
@ -167,8 +165,10 @@ namespace srslte {
|
|||
bool trace_enabled;
|
||||
uint32_t tti;
|
||||
bool agc_enabled;
|
||||
int offset;
|
||||
uint32_t sf_len;
|
||||
|
||||
char saved_args[128];
|
||||
char saved_devname[128];
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,9 @@ public:
|
|||
uint8_t direction_);
|
||||
void stop();
|
||||
|
||||
// GW interface
|
||||
bool is_drb_enabled(uint32_t lcid);
|
||||
|
||||
// RRC interface
|
||||
void reset();
|
||||
void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
mac_interface_timers *mac_timers);
|
||||
void configure(srslte_rlc_config_t cnfg);
|
||||
void reset();
|
||||
void stop();
|
||||
void empty_queue();
|
||||
|
||||
rlc_mode_t get_mode();
|
||||
|
|
|
@ -158,6 +158,7 @@ public:
|
|||
srslte::mac_interface_timers *mac_timers_) = 0;
|
||||
virtual void configure(srslte_rlc_config_t cnfg) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void empty_queue() = 0;
|
||||
|
||||
virtual rlc_mode_t get_mode() = 0;
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
|
||||
void configure(srslte_rlc_config_t cnfg);
|
||||
void reset();
|
||||
void stop();
|
||||
void empty_queue();
|
||||
bool active();
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
mac_interface_timers *mac_timers);
|
||||
void configure(srslte_rlc_config_t cnfg);
|
||||
void reset();
|
||||
void stop();
|
||||
void empty_queue();
|
||||
|
||||
rlc_mode_t get_mode();
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
mac_interface_timers *mac_timers_);
|
||||
void configure(srslte_rlc_config_t cnfg);
|
||||
void reset();
|
||||
void stop();
|
||||
void empty_queue();
|
||||
|
||||
rlc_mode_t get_mode();
|
||||
|
@ -124,7 +125,8 @@ private:
|
|||
* Timers
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
uint32_t reordering_timeout_id;
|
||||
srslte::timers::timer *reordering_timer;
|
||||
uint32_t reordering_timer_id;
|
||||
|
||||
bool pdu_lost;
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ void logger_file::init(std::string file) {
|
|||
filename = file;
|
||||
logfile = fopen(filename.c_str(), "w");
|
||||
if(logfile==NULL) {
|
||||
printf("Error: could not create log file, no messages will be logged");
|
||||
printf("Error: could not create log file, no messages will be logged!\n");
|
||||
}
|
||||
start();
|
||||
inited = true;
|
||||
|
|
|
@ -66,7 +66,7 @@ uint8_t* pdu_queue::request(uint32_t len)
|
|||
void pdu_queue::deallocate(uint8_t* pdu)
|
||||
{
|
||||
if (!pool.deallocate((pdu_t*) pdu)) {
|
||||
log_h->warning("Error deallocating from buffer pool: buffer not created in this pool.\n");
|
||||
log_h->warning("Error deallocating from buffer pool in deallocate(): buffer not created in this pool.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ bool pdu_queue::process_pdus()
|
|||
callback->process_pdu(pdu->ptr, pdu->len, pdu->tstamp);
|
||||
}
|
||||
if (!pool.deallocate(pdu)) {
|
||||
log_h->warning("Error deallocating from buffer pool: buffer not created in this pool.\n");
|
||||
log_h->warning("Error deallocating from buffer pool in process_pdus(): buffer not created in this pool.\n");
|
||||
}
|
||||
cnt++;
|
||||
have_data = true;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <string.h>
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
#include <srslte/srslte.h>
|
||||
|
||||
#include "srslte/config.h"
|
||||
|
||||
|
@ -72,54 +74,70 @@ static void set_default_filter(srslte_chest_dl_t *q, int filter_len) {
|
|||
*
|
||||
* This object depends on the srslte_refsignal_t object for creating the LTE CSR signal.
|
||||
*/
|
||||
|
||||
int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
|
||||
int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
bzero(q, sizeof(srslte_chest_dl_t));
|
||||
|
||||
ret = srslte_refsignal_cs_init(&q->csr_signal, cell);
|
||||
|
||||
ret = srslte_refsignal_cs_init(&q->csr_refs, max_prb);
|
||||
if (ret != SRSLTE_SUCCESS) {
|
||||
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
||||
q->mbsfn_refs = calloc(SRSLTE_MAX_MBSFN_AREA_IDS, sizeof(srslte_refsignal_t*));
|
||||
if (!q->mbsfn_refs) {
|
||||
fprintf(stderr, "Calloc error initializing mbsfn_refs (%d)\n", ret);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
int pilot_vec_size;
|
||||
if(SRSLTE_REFSIGNAL_MAX_NUM_SF_MBSFN(max_prb)>SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb)) {
|
||||
pilot_vec_size = SRSLTE_REFSIGNAL_MAX_NUM_SF_MBSFN(max_prb);
|
||||
}else{
|
||||
pilot_vec_size = SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb);
|
||||
}
|
||||
|
||||
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
|
||||
|
||||
|
||||
if (!q->tmp_noise) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
||||
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
|
||||
|
||||
if (!q->pilot_estimates) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
||||
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
|
||||
if (!q->pilot_estimates_average) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
||||
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
|
||||
|
||||
if (!q->pilot_recv_signal) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) {
|
||||
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*max_prb)) {
|
||||
fprintf(stderr, "Error initializing vector interpolator\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*cell.nof_prb, SRSLTE_NRE/2)) {
|
||||
if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*max_prb, SRSLTE_NRE/2)) {
|
||||
fprintf(stderr, "Error initializing interpolator\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_pss_generate(q->pss_signal, cell.id%3)) {
|
||||
fprintf(stderr, "Error initializing PSS signal for noise estimation\n");
|
||||
|
||||
if (srslte_interp_linear_init(&q->srslte_interp_lin_mbsfn, 6*max_prb, SRSLTE_NRE/6)) {
|
||||
fprintf(stderr, "Error initializing interpolator\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
|
@ -128,7 +146,6 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
|
|||
q->smooth_filter_len = 3;
|
||||
srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1);
|
||||
|
||||
q->cell = cell;
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
@ -142,14 +159,25 @@ clean_exit:
|
|||
|
||||
void srslte_chest_dl_free(srslte_chest_dl_t *q)
|
||||
{
|
||||
srslte_refsignal_cs_free(&q->csr_signal);
|
||||
int i;
|
||||
if(&q->csr_refs)
|
||||
srslte_refsignal_free(&q->csr_refs);
|
||||
|
||||
if (q->mbsfn_refs) {
|
||||
for (i=0; i<SRSLTE_MAX_MBSFN_AREA_IDS; i++) {
|
||||
if (q->mbsfn_refs[i]) {
|
||||
srslte_refsignal_free(q->mbsfn_refs[i]);
|
||||
}
|
||||
}
|
||||
free(q->mbsfn_refs);
|
||||
}
|
||||
|
||||
if (q->tmp_noise) {
|
||||
free(q->tmp_noise);
|
||||
}
|
||||
srslte_interp_linear_vector_free(&q->srslte_interp_linvec);
|
||||
srslte_interp_linear_free(&q->srslte_interp_lin);
|
||||
|
||||
srslte_interp_linear_free(&q->srslte_interp_lin_mbsfn);
|
||||
if (q->pilot_estimates) {
|
||||
free(q->pilot_estimates);
|
||||
}
|
||||
|
@ -162,10 +190,57 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q)
|
|||
bzero(q, sizeof(srslte_chest_dl_t));
|
||||
}
|
||||
|
||||
|
||||
int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t *q, uint16_t mbsfn_area_id){
|
||||
if(!q->mbsfn_refs[mbsfn_area_id]){
|
||||
q->mbsfn_refs[mbsfn_area_id] = calloc(1, sizeof(srslte_refsignal_t));
|
||||
}
|
||||
if(q->mbsfn_refs[mbsfn_area_id]) {
|
||||
if(srslte_refsignal_mbsfn_init(q->mbsfn_refs[mbsfn_area_id], q->cell, mbsfn_area_id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
ret = srslte_refsignal_cs_set_cell(&q->csr_refs, cell);
|
||||
if (ret != SRSLTE_SUCCESS) {
|
||||
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_pss_generate(q->pss_signal, cell.id%3)) {
|
||||
fprintf(stderr, "Error initializing PSS signal for noise estimation\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_interp_linear_vector_resize(&q->srslte_interp_linvec, SRSLTE_NRE*q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initializing vector interpolator\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_interp_linear_resize(&q->srslte_interp_lin, 2*q->cell.nof_prb, SRSLTE_NRE/2)) {
|
||||
fprintf(stderr, "Error initializing interpolator\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Uses the difference between the averaged and non-averaged pilot estimates */
|
||||
static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id)
|
||||
{
|
||||
int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
|
||||
|
||||
/* Substract noisy pilot estimates */
|
||||
srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref);
|
||||
|
||||
|
@ -223,46 +298,70 @@ static float estimate_noise_empty_sc(srslte_chest_dl_t *q, cf_t *input) {
|
|||
|
||||
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)]
|
||||
|
||||
static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id)
|
||||
static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id, srslte_sf_t ch_mode)
|
||||
{
|
||||
/* interpolate the symbols with references in the freq domain */
|
||||
uint32_t l;
|
||||
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id);
|
||||
|
||||
uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN ) ? srslte_refsignal_mbsfn_nof_symbols() + 1 : srslte_refsignal_cs_nof_symbols(port_id);
|
||||
uint32_t fidx_offset = 0;
|
||||
/* Interpolate in the frequency domain */
|
||||
for (l=0;l<nsymbols;l++) {
|
||||
uint32_t fidx_offset = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0);
|
||||
srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2*q->cell.nof_prb*l],
|
||||
&ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE],
|
||||
fidx_offset, SRSLTE_NRE/2-fidx_offset);
|
||||
|
||||
// we add one to nsymbols to allow for inclusion of the non-mbms references in the channel estimation
|
||||
for (l=0;l<(nsymbols);l++) {
|
||||
if (ch_mode == SRSLTE_SF_MBSFN) {
|
||||
if (l == 0) {
|
||||
fidx_offset = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0);
|
||||
srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2*q->cell.nof_prb*l],
|
||||
&ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE],
|
||||
fidx_offset, SRSLTE_NRE/2-fidx_offset);
|
||||
} else {
|
||||
fidx_offset = srslte_refsignal_mbsfn_fidx(l - 1);
|
||||
srslte_interp_linear_offset(&q->srslte_interp_lin_mbsfn, &pilot_estimates[(2*q->cell.nof_prb) + 6*q->cell.nof_prb*(l - 1)],
|
||||
&ce[srslte_refsignal_mbsfn_nsymbol(l - 1) * q->cell.nof_prb * SRSLTE_NRE],
|
||||
fidx_offset, SRSLTE_NRE/6-fidx_offset);
|
||||
}
|
||||
} else {
|
||||
fidx_offset = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0);
|
||||
srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2*q->cell.nof_prb*l],
|
||||
&ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE],
|
||||
fidx_offset, SRSLTE_NRE/2-fidx_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Now interpolate in the time domain between symbols */
|
||||
if (SRSLTE_CP_ISNORM(q->cell.cp)) {
|
||||
if (nsymbols == 4) {
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 3, 2);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 4, 3);
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 4, 2);
|
||||
if (ch_mode == SRSLTE_SF_MBSFN) {
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(2), &cesymb(1), 2, 1);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(2), &cesymb(6), &cesymb(3), 4, 3);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(7), 4, 3);
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(10), &cesymb(11), 4, 1);
|
||||
} else {
|
||||
if (SRSLTE_CP_ISNORM(q->cell.cp)) {
|
||||
if (nsymbols == 4) {
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 3, 2);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 4, 3);
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 4, 2);
|
||||
} else {
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(1), &cesymb(0), 7, 1);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 7, 6);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 7, 5);
|
||||
}
|
||||
} else {
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(1), &cesymb(0), 7, 1);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 7, 6);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 7, 5);
|
||||
}
|
||||
} else {
|
||||
if (nsymbols == 4) {
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 3, 2);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 3, 2);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 3, 2);
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 3, 2);
|
||||
} else {
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(1), &cesymb(0), 6, 1);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 6, 5);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 6, 4);
|
||||
}
|
||||
if (nsymbols == 4) {
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 3, 2);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 3, 2);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 3, 2);
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 3, 2);
|
||||
} else {
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(1), &cesymb(0), 6, 1);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 6, 5);
|
||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 6, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) {
|
||||
if (filter_len < SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN) {
|
||||
if (filter) {
|
||||
|
@ -289,9 +388,9 @@ void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w)
|
|||
q->smooth_filter[1] = 1-2*w;
|
||||
}
|
||||
|
||||
static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id) {
|
||||
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id);
|
||||
uint32_t nref = 2*q->cell.nof_prb;
|
||||
static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) {
|
||||
uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id);
|
||||
uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb;
|
||||
|
||||
// Average in the frequency domain
|
||||
for (int l=0;l<nsymbols;l++) {
|
||||
|
@ -311,24 +410,16 @@ float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id)
|
|||
return rssi/nsymbols;
|
||||
}
|
||||
|
||||
int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id)
|
||||
{
|
||||
/* Get references from the input signal */
|
||||
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
|
||||
|
||||
/* Use the known CSR signal to compute Least-squares estimates */
|
||||
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_signal.pilots[port_id/2][sf_idx],
|
||||
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
|
||||
if (ce != NULL) {
|
||||
|
||||
void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){
|
||||
if (ce != NULL) {
|
||||
/* Smooth estimates (if applicable) and interpolate */
|
||||
if (q->smooth_filter_len == 0 || (q->smooth_filter_len == 3 && q->smooth_filter[0] == 0)) {
|
||||
interpolate_pilots(q, q->pilot_estimates, ce, port_id);
|
||||
interpolate_pilots(q, q->pilot_estimates, ce, port_id, ch_mode);
|
||||
} else {
|
||||
average_pilots(q, q->pilot_estimates, q->pilot_estimates_average, port_id);
|
||||
interpolate_pilots(q, q->pilot_estimates_average, ce, port_id);
|
||||
average_pilots(q, q->pilot_estimates, q->pilot_estimates_average, port_id, ch_mode);
|
||||
interpolate_pilots(q, q->pilot_estimates_average, ce, port_id, ch_mode);
|
||||
}
|
||||
|
||||
|
||||
/* Estimate noise power */
|
||||
if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && q->smooth_filter_len > 0) {
|
||||
q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id);
|
||||
|
@ -340,8 +431,7 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
|
|||
if (sf_idx == 0 || sf_idx == 5) {
|
||||
q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute RSRP for the channel estimates in this port */
|
||||
|
@ -350,10 +440,44 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
|
|||
/* compute rssi only for port 0 */
|
||||
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
|
||||
}
|
||||
}
|
||||
|
||||
int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id)
|
||||
{
|
||||
/* Get references from the input signal */
|
||||
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
|
||||
|
||||
/* Use the known CSR signal to compute Least-squares estimates */
|
||||
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx],
|
||||
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
|
||||
|
||||
chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_NORM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int srslte_chest_dl_estimate_port_mbsfn(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, uint16_t mbsfn_area_id)
|
||||
{
|
||||
|
||||
/* Use the known CSR signal to compute Least-squares estimates */
|
||||
srslte_refsignal_mbsfn_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
|
||||
// estimate for non-mbsfn section of subframe
|
||||
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx],
|
||||
q->pilot_estimates, (2*q->cell.nof_prb));
|
||||
|
||||
srslte_vec_prod_conj_ccc(q->pilot_recv_signal+(2*q->cell.nof_prb), q->mbsfn_refs[mbsfn_area_id]->pilots[port_id/2][sf_idx],
|
||||
q->pilot_estimates+(2*q->cell.nof_prb), SRSLTE_REFSIGNAL_NUM_SF_MBSFN(q->cell.nof_prb, port_id)-(2*q->cell.nof_prb));
|
||||
|
||||
|
||||
|
||||
chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_MBSFN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t nof_rx_antennas)
|
||||
{
|
||||
for (uint32_t rxant_id=0;rxant_id<nof_rx_antennas;rxant_id++) {
|
||||
|
@ -370,7 +494,7 @@ int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_
|
|||
int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input, cf_t *ce[SRSLTE_MAX_PORTS], uint32_t sf_idx)
|
||||
{
|
||||
uint32_t port_id;
|
||||
|
||||
|
||||
for (port_id=0;port_id<q->cell.nof_ports;port_id++) {
|
||||
if (srslte_chest_dl_estimate_port(q, input, ce[port_id], sf_idx, port_id, 0)) {
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -380,6 +504,21 @@ int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input, cf_t *ce[SRSLTE_
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_chest_dl_estimate_multi_mbsfn(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t nof_rx_antennas, uint16_t mbsfn_area_id)
|
||||
{
|
||||
for (uint32_t rxant_id=0;rxant_id<nof_rx_antennas;rxant_id++) {
|
||||
for (uint32_t port_id=0;port_id<q->cell.nof_ports;port_id++) {
|
||||
if (srslte_chest_dl_estimate_port_mbsfn(q, input[rxant_id], ce[port_id][rxant_id], sf_idx, port_id, rxant_id, mbsfn_area_id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
q->last_nof_antennas = nof_rx_antennas;
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) {
|
||||
float n = 0;
|
||||
for (int i=0;i<q->last_nof_antennas;i++) {
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <string.h>
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
#include <srslte/srslte.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
|
||||
#include "srslte/config.h"
|
||||
|
||||
|
@ -43,6 +45,9 @@
|
|||
#define NOF_REFS_SYM (q->cell.nof_prb*SRSLTE_NRE)
|
||||
#define NOF_REFS_SF (NOF_REFS_SYM*2) // 2 reference symbols per subframe
|
||||
|
||||
#define MAX_REFS_SYM (max_prb*SRSLTE_NRE)
|
||||
#define MAX_REFS_SF (max_prb*SRSLTE_NRE*2) // 2 reference symbols per subframe
|
||||
|
||||
/** 3GPP LTE Downlink channel estimator and equalizer.
|
||||
* Estimates the channel in the resource elements transmitting references and interpolates for the rest
|
||||
* of the resource grid.
|
||||
|
@ -52,52 +57,49 @@
|
|||
* This object depends on the srslte_refsignal_t object for creating the LTE CSR signal.
|
||||
*/
|
||||
|
||||
int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
|
||||
int srslte_chest_ul_init(srslte_chest_ul_t *q, uint32_t max_prb)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
bzero(q, sizeof(srslte_chest_ul_t));
|
||||
|
||||
q->cell = cell;
|
||||
|
||||
ret = srslte_refsignal_ul_init(&q->dmrs_signal, cell);
|
||||
ret = srslte_refsignal_ul_init(&q->dmrs_signal, max_prb);
|
||||
if (ret != SRSLTE_SUCCESS) {
|
||||
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
|
||||
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
|
||||
if (!q->tmp_noise) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
|
||||
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
|
||||
if (!q->pilot_estimates) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
for (int i=0;i<4;i++) {
|
||||
q->pilot_estimates_tmp[i] = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
|
||||
q->pilot_estimates_tmp[i] = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
|
||||
if (!q->pilot_estimates_tmp[i]) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
}
|
||||
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1));
|
||||
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * (MAX_REFS_SF+1));
|
||||
if (!q->pilot_recv_signal) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1));
|
||||
q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (MAX_REFS_SF+1));
|
||||
if (!q->pilot_known_signal) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, NOF_REFS_SYM)) {
|
||||
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, MAX_REFS_SYM)) {
|
||||
fprintf(stderr, "Error initializing vector interpolator\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
@ -105,12 +107,17 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
|
|||
q->smooth_filter_len = 3;
|
||||
srslte_chest_ul_set_smooth_filter3_coeff(q, 0.3333);
|
||||
|
||||
q->dmrs_signal_configured = false;
|
||||
q->dmrs_signal_configured = false;
|
||||
|
||||
if (srslte_refsignal_dmrs_pusch_pregen_init(&q->dmrs_signal, &q->dmrs_pregen, max_prb)) {
|
||||
fprintf(stderr, "Error allocating memory for pregenerated signals\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
|
||||
clean_exit:
|
||||
if (ret != SRSLTE_SUCCESS) {
|
||||
srslte_chest_ul_free(q);
|
||||
|
@ -120,9 +127,8 @@ clean_exit:
|
|||
|
||||
void srslte_chest_ul_free(srslte_chest_ul_t *q)
|
||||
{
|
||||
if (q->dmrs_signal_configured) {
|
||||
srslte_refsignal_dmrs_pusch_pregen_free(&q->dmrs_signal, &q->dmrs_pregen);
|
||||
}
|
||||
srslte_refsignal_dmrs_pusch_pregen_free(&q->dmrs_signal, &q->dmrs_pregen);
|
||||
|
||||
srslte_refsignal_ul_free(&q->dmrs_signal);
|
||||
if (q->tmp_noise) {
|
||||
free(q->tmp_noise);
|
||||
|
@ -146,6 +152,30 @@ void srslte_chest_ul_free(srslte_chest_ul_t *q)
|
|||
bzero(q, sizeof(srslte_chest_ul_t));
|
||||
}
|
||||
|
||||
int srslte_chest_ul_set_cell(srslte_chest_ul_t *q, srslte_cell_t cell)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
ret = srslte_refsignal_ul_set_cell(&q->dmrs_signal, cell);
|
||||
if (ret != SRSLTE_SUCCESS) {
|
||||
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_interp_linear_vector_resize(&q->srslte_interp_linvec, NOF_REFS_SYM)) {
|
||||
fprintf(stderr, "Error initializing vector interpolator\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
|
|
|
@ -75,17 +75,40 @@ uint32_t srslte_refsignal_cs_v(uint32_t port_id, uint32_t ref_symbol_idx)
|
|||
|
||||
uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id)
|
||||
{
|
||||
uint32_t ret;
|
||||
if (port_id < 2) {
|
||||
return 4;
|
||||
ret = 4;
|
||||
} else {
|
||||
return 2;
|
||||
ret = 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t srslte_refsignal_mbsfn_nof_symbols()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
inline uint32_t srslte_refsignal_cs_fidx(srslte_cell_t cell, uint32_t l, uint32_t port_id, uint32_t m) {
|
||||
return 6*m + ((srslte_refsignal_cs_v(port_id, l) + (cell.id % 6)) % 6);
|
||||
}
|
||||
|
||||
inline uint32_t srslte_refsignal_mbsfn_fidx(uint32_t l)
|
||||
{
|
||||
|
||||
uint32_t ret = 0;
|
||||
if(l == 0){
|
||||
ret = 0;
|
||||
}else if (l == 1){
|
||||
ret = 1;
|
||||
}else if(l == 2){
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t port_id) {
|
||||
if (port_id < 2) {
|
||||
if (l % 2) {
|
||||
|
@ -97,12 +120,134 @@ inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t
|
|||
return 1+l*SRSLTE_CP_NSYMB(cp);
|
||||
}
|
||||
}
|
||||
inline uint32_t srslte_refsignal_mbsfn_nsymbol(uint32_t l)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
if(l == 0){
|
||||
ret = 2;
|
||||
} else if (l == 1) {
|
||||
ret = 6;
|
||||
} else if (l == 2){
|
||||
ret = 10;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srslte_refsignal_mbsfn_gen_seq(srslte_refsignal_t * q, srslte_cell_t cell, uint32_t N_mbsfn_id)
|
||||
{
|
||||
uint32_t c_init;
|
||||
uint32_t i, ns, l, p;
|
||||
uint32_t mp;
|
||||
int ret = SRSLTE_ERROR;
|
||||
|
||||
srslte_sequence_t seq_mbsfn;
|
||||
bzero(&seq_mbsfn, sizeof(srslte_sequence_t));
|
||||
if (srslte_sequence_init(&seq_mbsfn, 20* SRSLTE_MAX_PRB)) {
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
for(ns=0; ns<SRSLTE_NSUBFRAMES_X_FRAME;ns++){
|
||||
for(p=0;p<2;p++) {
|
||||
uint32_t nsymbols = 3; // replace with function
|
||||
for(l=0;l<nsymbols;l++) {
|
||||
uint32_t lp = (srslte_refsignal_mbsfn_nsymbol(l))%6;
|
||||
uint32_t slot =(l)?(ns*2+1):(ns*2);
|
||||
c_init = 512*(7*(slot+1)+lp+1)*(2*N_mbsfn_id + 1) + N_mbsfn_id;
|
||||
srslte_sequence_set_LTE_pr(&seq_mbsfn,SRSLTE_MAX_PRB*20 ,c_init);
|
||||
for(i=0;i< 6*q->cell.nof_prb;i++) {
|
||||
mp = i + 3*(SRSLTE_MAX_PRB - cell.nof_prb);
|
||||
q->pilots[p][ns][ SRSLTE_REFSIGNAL_PILOT_IDX_MBSFN(i, l ,q->cell)] = (1 - 2 * (float) seq_mbsfn.c[2 * mp]) / sqrt(2) +_Complex_I * (1 - 2 * (float) seq_mbsfn.c[2 * mp + 1]) / sqrt(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
srslte_sequence_free(&seq_mbsfn);
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
free_and_exit:
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
srslte_sequence_free(&seq_mbsfn);
|
||||
srslte_refsignal_free(q);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
|
||||
int srslte_refsignal_mbsfn_init(srslte_refsignal_t * q, srslte_cell_t cell, uint16_t mbsfn_area_id)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
uint32_t i, p;
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
bzero(q, sizeof(srslte_refsignal_t));
|
||||
q->cell = cell;
|
||||
q->type = SRSLTE_SF_MBSFN;
|
||||
q->mbsfn_area_id = mbsfn_area_id;
|
||||
|
||||
for (p=0;p<2;p++) {
|
||||
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
|
||||
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * q->cell.nof_prb * 18);
|
||||
if (!q->pilots[p][i]) {
|
||||
perror("malloc");
|
||||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(srslte_refsignal_mbsfn_gen_seq(q, q->cell, q->mbsfn_area_id)) {
|
||||
goto free_and_exit;
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
free_and_exit:
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
srslte_refsignal_free(q);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Allocates memory for the 20 slots in a subframe
|
||||
*/
|
||||
int srslte_refsignal_cs_init(srslte_refsignal_t * q, uint32_t max_prb)
|
||||
{
|
||||
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL)
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
bzero(q, sizeof(srslte_refsignal_t));
|
||||
for (int p=0;p<2;p++) {
|
||||
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
|
||||
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(max_prb, 2*p));
|
||||
if (!q->pilots[p][i]) {
|
||||
perror("malloc");
|
||||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
free_and_exit:
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
srslte_refsignal_free(q);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
|
||||
* the 20 slots in a subframe
|
||||
*/
|
||||
int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
|
||||
int srslte_refsignal_cs_set_cell(srslte_refsignal_t * q, srslte_cell_t cell)
|
||||
{
|
||||
|
||||
uint32_t c_init;
|
||||
|
@ -112,85 +257,68 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
|
|||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
bzero(q, sizeof(srslte_refsignal_cs_t));
|
||||
bzero(&seq, sizeof(srslte_sequence_t));
|
||||
if (srslte_sequence_init(&seq, 2 * 2 * SRSLTE_MAX_PRB)) {
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
if (SRSLTE_CP_ISNORM(cell.cp)) {
|
||||
N_cp = 1;
|
||||
} else {
|
||||
N_cp = 0;
|
||||
}
|
||||
|
||||
q->cell = cell;
|
||||
|
||||
for (p=0;p<2;p++) {
|
||||
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
|
||||
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 2*p));
|
||||
if (!q->pilots[p][i]) {
|
||||
perror("malloc");
|
||||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
|
||||
for (p=0;p<2;p++) {
|
||||
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2;
|
||||
for (l = 0; l < nsymbols; l++) {
|
||||
/* Compute sequence init value */
|
||||
uint32_t lp = srslte_refsignal_cs_nsymbol(l, cell.cp, 2*p);
|
||||
c_init = 1024 * (7 * (ns + 1) + lp + 1) * (2 * cell.id + 1)
|
||||
+ 2 * cell.id + N_cp;
|
||||
|
||||
/* generate sequence for this symbol and slot */
|
||||
srslte_sequence_set_LTE_pr(&seq, c_init);
|
||||
|
||||
/* Compute signal */
|
||||
for (i = 0; i < 2*q->cell.nof_prb; i++) {
|
||||
mp = i + SRSLTE_MAX_PRB - cell.nof_prb;
|
||||
/* save signal */
|
||||
q->pilots[p][ns/2][SRSLTE_REFSIGNAL_PILOT_IDX(i,(ns%2)*nsymbols+l,q->cell)] =
|
||||
(1 - 2 * (float) seq.c[2 * mp]) / sqrt(2) +
|
||||
_Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
|
||||
bzero(&seq, sizeof(srslte_sequence_t));
|
||||
if (srslte_sequence_init(&seq, 2*2*SRSLTE_MAX_PRB)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (SRSLTE_CP_ISNORM(cell.cp)) {
|
||||
N_cp = 1;
|
||||
} else {
|
||||
N_cp = 0;
|
||||
}
|
||||
|
||||
for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
|
||||
for (p=0;p<2;p++) {
|
||||
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2;
|
||||
for (l = 0; l < nsymbols; l++) {
|
||||
/* Compute sequence init value */
|
||||
uint32_t lp = srslte_refsignal_cs_nsymbol(l, cell.cp, 2*p);
|
||||
c_init = 1024 * (7 * (ns + 1) + lp + 1) * (2 * cell.id + 1)
|
||||
+ 2 * cell.id + N_cp;
|
||||
|
||||
/* generate sequence for this symbol and slot */
|
||||
srslte_sequence_set_LTE_pr(&seq, 2*2*SRSLTE_MAX_PRB, c_init);
|
||||
|
||||
/* Compute signal */
|
||||
for (i = 0; i < 2*q->cell.nof_prb; i++) {
|
||||
mp = i + SRSLTE_MAX_PRB - cell.nof_prb;
|
||||
/* save signal */
|
||||
q->pilots[p][ns/2][SRSLTE_REFSIGNAL_PILOT_IDX(i,(ns%2)*nsymbols+l,q->cell)] =
|
||||
(1 - 2 * (float) seq.c[2 * mp]) / sqrt(2) +
|
||||
_Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
srslte_sequence_free(&seq);
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
free_and_exit:
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
srslte_sequence_free(&seq);
|
||||
srslte_refsignal_cs_free(q);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */
|
||||
void srslte_refsignal_cs_free(srslte_refsignal_cs_t * q)
|
||||
void srslte_refsignal_free(srslte_refsignal_t * q)
|
||||
{
|
||||
int i, p;
|
||||
|
||||
for (p=0;p<2;p++) {
|
||||
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
|
||||
for (int p=0;p<2;p++) {
|
||||
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
|
||||
if (q->pilots[p][i]) {
|
||||
free(q->pilots[p][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
bzero(q, sizeof(srslte_refsignal_cs_t));
|
||||
bzero(q, sizeof(srslte_refsignal_t));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Maps a reference signal initialized with srslte_refsignal_cs_init() into an array of subframe symbols */
|
||||
int srslte_refsignal_cs_put_sf(srslte_cell_t cell, uint32_t port_id, cf_t *pilots, cf_t *sf_symbols)
|
||||
{
|
||||
|
@ -218,6 +346,45 @@ int srslte_refsignal_cs_put_sf(srslte_cell_t cell, uint32_t port_id, cf_t *pilot
|
|||
}
|
||||
}
|
||||
|
||||
SRSLTE_API int srslte_refsignal_mbsfn_put_sf(srslte_cell_t cell,
|
||||
uint32_t port_id,
|
||||
cf_t *cs_pilots,
|
||||
cf_t *mbsfn_pilots,
|
||||
cf_t *sf_symbols)
|
||||
{
|
||||
uint32_t i, l;
|
||||
uint32_t fidx;
|
||||
|
||||
if (srslte_cell_isvalid(&cell) &&
|
||||
srslte_portid_isvalid(port_id) &&
|
||||
cs_pilots != NULL &&
|
||||
mbsfn_pilots != NULL &&
|
||||
sf_symbols != NULL)
|
||||
{
|
||||
// adding CS refs for the non-mbsfn section of the sub-frame
|
||||
fidx = ((srslte_refsignal_cs_v(port_id, 0) + (cell.id % 6)) % 6);
|
||||
for (i = 0; i < 2*cell.nof_prb; i++) {
|
||||
sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, 0, fidx)] = cs_pilots[SRSLTE_REFSIGNAL_PILOT_IDX(i,0,cell)];
|
||||
fidx += SRSLTE_NRE/2; // 1 reference every 6 RE
|
||||
}
|
||||
|
||||
for (l = 0; l<srslte_refsignal_mbsfn_nof_symbols(); l++) {
|
||||
uint32_t nsymbol = srslte_refsignal_mbsfn_nsymbol(l);
|
||||
fidx = srslte_refsignal_mbsfn_fidx(l);
|
||||
for (i = 0; i < 6*cell.nof_prb; i++) {
|
||||
sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, nsymbol, fidx)] = mbsfn_pilots[SRSLTE_REFSIGNAL_PILOT_IDX_MBSFN(i,l,cell)];
|
||||
fidx += SRSLTE_NRE/6;
|
||||
}
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Copies the RE containing references from an array of subframe symbols to the pilots array. */
|
||||
int srslte_refsignal_cs_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_symbols, cf_t *pilots)
|
||||
{
|
||||
|
@ -244,4 +411,39 @@ int srslte_refsignal_cs_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_sy
|
|||
}
|
||||
}
|
||||
|
||||
int srslte_refsignal_mbsfn_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_symbols, cf_t *pilots)
|
||||
{
|
||||
uint32_t i, l;
|
||||
uint32_t fidx;
|
||||
uint32_t nsymbol;
|
||||
if (srslte_cell_isvalid(&cell) &&
|
||||
srslte_portid_isvalid(port_id) &&
|
||||
pilots != NULL &&
|
||||
sf_symbols != NULL)
|
||||
{
|
||||
// getting refs from non mbsfn section of subframe
|
||||
nsymbol = srslte_refsignal_cs_nsymbol(0, cell.cp, port_id);
|
||||
fidx = ((srslte_refsignal_cs_v(port_id, 0) + (cell.id % 6)) % 6);
|
||||
for (i = 0; i < 2*cell.nof_prb; i++) {
|
||||
pilots[SRSLTE_REFSIGNAL_PILOT_IDX(i,0,cell)] = sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, nsymbol, fidx)];
|
||||
fidx += SRSLTE_NRE/2; // 2 references per PRB
|
||||
}
|
||||
|
||||
for (l = 0; l< srslte_refsignal_mbsfn_nof_symbols() ;l++){
|
||||
nsymbol = srslte_refsignal_mbsfn_nsymbol(l);
|
||||
fidx = srslte_refsignal_mbsfn_fidx(l);
|
||||
for (i = 0; i < 6*cell.nof_prb; i++) {
|
||||
pilots[SRSLTE_REFSIGNAL_PILOT_IDX_MBSFN(i,l,cell) + (2*cell.nof_prb)] = sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, nsymbol, fidx)];
|
||||
fidx += SRSLTE_NRE/6;
|
||||
}
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <complex.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
#include "srslte/phy/ch_estimation/refsignal_ul.h"
|
||||
|
@ -138,8 +139,8 @@ static int generate_n_prs(srslte_refsignal_ul_t * q) {
|
|||
}
|
||||
q->n_prs_pusch[delta_ss][ns] = n_prs;
|
||||
}
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
srslte_sequence_free(&seq);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
@ -160,9 +161,9 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->v_pusch[ns][delta_ss] = seq.c[ns];
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
}
|
||||
srslte_sequence_free(&seq);
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -170,46 +171,24 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
|
|||
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
|
||||
*
|
||||
*/
|
||||
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell)
|
||||
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, uint32_t max_prb)
|
||||
{
|
||||
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL && srslte_cell_isvalid(&cell)) {
|
||||
if (q != NULL) {
|
||||
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
bzero(q, sizeof(srslte_refsignal_ul_t));
|
||||
q->cell = cell;
|
||||
|
||||
|
||||
// Allocate temporal buffer for computing signal argument
|
||||
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
|
||||
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t));
|
||||
if (!q->tmp_arg) {
|
||||
perror("malloc");
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
srslte_pucch_cfg_default(&q->pucch_cfg);
|
||||
|
||||
// Precompute n_prs
|
||||
if (generate_n_prs(q)) {
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
// Precompute group hopping values u.
|
||||
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
// Precompute sequence hopping values v. Uses f_ss_pusch
|
||||
if (generate_srslte_sequence_hopping_v(q)) {
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
free_and_exit:
|
||||
|
@ -226,6 +205,45 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
|
|||
bzero(q, sizeof(srslte_refsignal_ul_t));
|
||||
}
|
||||
|
||||
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
|
||||
*
|
||||
*/
|
||||
int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t * q, srslte_cell_t cell)
|
||||
{
|
||||
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL && srslte_cell_isvalid(&cell)) {
|
||||
|
||||
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
|
||||
srslte_pucch_cfg_default(&q->pucch_cfg);
|
||||
|
||||
// Precompute n_prs
|
||||
if (generate_n_prs(q)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Precompute group hopping values u.
|
||||
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Precompute sequence hopping values v. Uses f_ss_pusch
|
||||
if (generate_srslte_sequence_hopping_v(q)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
|
@ -363,15 +381,38 @@ void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t
|
|||
|
||||
}
|
||||
|
||||
int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen,
|
||||
uint32_t max_prb)
|
||||
{
|
||||
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
|
||||
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
|
||||
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), max_prb + 1);
|
||||
if (pregen->r[cs][sf_idx]) {
|
||||
for (uint32_t n=0;n<=max_prb;n++) {
|
||||
if (srslte_dft_precoding_valid_prb(n)) {
|
||||
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
|
||||
if (pregen->r[cs][sf_idx][n]) {
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen)
|
||||
{
|
||||
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
|
||||
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
|
||||
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), q->cell.nof_prb + 1);
|
||||
if (pregen->r[cs][sf_idx]) {
|
||||
for (uint32_t n=0;n<=q->cell.nof_prb;n++) {
|
||||
if (srslte_dft_precoding_valid_prb(n)) {
|
||||
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
|
||||
if (pregen->r[cs][sf_idx][n]) {
|
||||
if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) {
|
||||
return SRSLTE_ERROR;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <complex.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
|
@ -128,10 +129,13 @@ int main(int argc, char **argv) {
|
|||
cid = cell.id;
|
||||
max_cid = cell.id;
|
||||
}
|
||||
|
||||
if (srslte_chest_dl_init(&est, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
goto do_exit;
|
||||
}
|
||||
while(cid <= max_cid) {
|
||||
cell.id = cid;
|
||||
if (srslte_chest_dl_init(&est, cell)) {
|
||||
if (srslte_chest_dl_set_cell(&est, cell)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
goto do_exit;
|
||||
}
|
||||
|
@ -148,7 +152,7 @@ int main(int argc, char **argv) {
|
|||
bzero(h, sizeof(cf_t) * num_re);
|
||||
|
||||
srslte_refsignal_cs_put_sf(cell, n_port,
|
||||
est.csr_signal.pilots[n_port/2][sf_idx], input);
|
||||
est.csr_refs.pilots[n_port/2][sf_idx], input);
|
||||
|
||||
for (i=0;i<2*SRSLTE_CP_NSYMB(cell.cp);i++) {
|
||||
for (j=0;j<cell.nof_prb * SRSLTE_NRE;j++) {
|
||||
|
@ -214,10 +218,10 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
}
|
||||
srslte_chest_dl_free(&est);
|
||||
cid+=10;
|
||||
INFO("cid=%d\n", cid);
|
||||
}
|
||||
srslte_chest_dl_free(&est);
|
||||
|
||||
|
||||
ret = 0;
|
||||
|
|
|
@ -125,13 +125,17 @@ int main(int argc, char **argv) {
|
|||
max_cid = cell.id;
|
||||
}
|
||||
printf("max_cid=%d, cid=%d, cell.id=%d\n", max_cid, cid, cell.id);
|
||||
if (srslte_chest_ul_init(&est, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
goto do_exit;
|
||||
}
|
||||
while(cid <= max_cid) {
|
||||
cell.id = cid;
|
||||
if (srslte_chest_ul_init(&est, cell)) {
|
||||
if (srslte_chest_ul_set_cell(&est, cell)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
|
||||
for (int n=6;n<=cell.nof_prb;n+=5) {
|
||||
if (srslte_dft_precoding_valid_prb(n)) {
|
||||
for (int delta_ss=29;delta_ss<SRSLTE_NOF_DELTA_SS;delta_ss++) {
|
||||
|
@ -213,9 +217,9 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
cid+=10;
|
||||
printf("cid=%d\n", cid);
|
||||
srslte_chest_ul_free(&est);
|
||||
}
|
||||
|
||||
srslte_chest_ul_free(&est);
|
||||
|
||||
if (fmatlab) {
|
||||
fprintf(fmatlab, "input=");
|
||||
|
|
|
@ -81,7 +81,12 @@ int main(int argc, char **argv) {
|
|||
|
||||
parse_args(argc,argv);
|
||||
|
||||
if (srslte_refsignal_ul_init(&refs, cell)) {
|
||||
if (srslte_refsignal_ul_init(&refs, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initializing UL reference signal\n");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
if (srslte_refsignal_ul_set_cell(&refs, cell)) {
|
||||
fprintf(stderr, "Error initializing UL reference signal\n");
|
||||
goto do_exit;
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ int srslte_symbol_sz_power2(uint32_t nof_prb) {
|
|||
return 1024;
|
||||
} else if (nof_prb<=75) {
|
||||
return 1536;
|
||||
} else if (nof_prb<=100) {
|
||||
} else if (nof_prb<=110) {
|
||||
return 2048;
|
||||
} else {
|
||||
return -1;
|
||||
|
@ -257,7 +257,7 @@ int srslte_symbol_sz(uint32_t nof_prb) {
|
|||
return 768;
|
||||
} else if (nof_prb<=75) {
|
||||
return 1024;
|
||||
} else if (nof_prb<=100) {
|
||||
} else if (nof_prb<=110) {
|
||||
return 1536;
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -605,7 +605,7 @@ int srslte_band_get_fd_region(enum band_geographical_area region, srslte_earfcn_
|
|||
|
||||
/* Returns the interval tti1-tti2 mod 10240 */
|
||||
uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2) {
|
||||
if (tti1 > tti2) {
|
||||
if (tti1 >= tti2) {
|
||||
return tti1-tti2;
|
||||
} else {
|
||||
return 10240-tti2+tti1;
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <srslte/phy/common/sequence.h>
|
||||
|
||||
#include "srslte/phy/common/sequence.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
@ -35,26 +36,75 @@
|
|||
|
||||
#define Nc 1600
|
||||
|
||||
#define MAX_SEQ_LEN (128*1024)
|
||||
|
||||
#define static_memory
|
||||
|
||||
/*
|
||||
* Pseudo Random Sequence generation.
|
||||
* It follows the 3GPP Release 8 (LTE) 36.211
|
||||
* Section 7.2
|
||||
*/
|
||||
void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t seed) {
|
||||
#ifdef static_memory
|
||||
static uint8_t x1[Nc+MAX_SEQ_LEN+31];
|
||||
static uint8_t x2[Nc+MAX_SEQ_LEN+31];
|
||||
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
|
||||
int n;
|
||||
|
||||
if (len > q->max_len) {
|
||||
fprintf(stderr, "Error generating pseudo-random sequence: len %d exceeds maximum len %d\n",
|
||||
len, MAX_SEQ_LEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > q->max_len) {
|
||||
fprintf(stderr, "Error generating pseudo-random sequence: len %d is greater than allocated len %d\n",
|
||||
len, q->max_len);
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
for (n = 0; n < 31; n++) {
|
||||
x2[n] = (seed >> n) & 0x1;
|
||||
}
|
||||
x1[0] = 1;
|
||||
|
||||
for (n = 0; n < Nc + len; n++) {
|
||||
x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1;
|
||||
x2[n + 31] = (x2[n + 3] + x2[n + 2] + x2[n+1] + x2[n]) & 0x1;
|
||||
}
|
||||
|
||||
for (n = 0; n < len; n++) {
|
||||
q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
|
||||
int n;
|
||||
uint32_t *x1, *x2;
|
||||
|
||||
x1 = calloc(Nc + q->len + 31, sizeof(uint32_t));
|
||||
if (len > q->max_len) {
|
||||
fprintf(stderr, "Error generating pseudo-random sequence: len %d is greater than allocated len %d\n",
|
||||
len, q->max_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
x1 = calloc(Nc + len + 31, sizeof(uint32_t));
|
||||
if (!x1) {
|
||||
perror("calloc");
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
x2 = calloc(Nc + q->len + 31, sizeof(uint32_t));
|
||||
x2 = calloc(Nc + len + 31, sizeof(uint32_t));
|
||||
if (!x2) {
|
||||
free(x1);
|
||||
perror("calloc");
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (n = 0; n < 31; n++) {
|
||||
|
@ -62,25 +112,29 @@ void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t seed) {
|
|||
}
|
||||
x1[0] = 1;
|
||||
|
||||
for (n = 0; n < Nc + q->len; n++) {
|
||||
for (n = 0; n < Nc + len; n++) {
|
||||
x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1;
|
||||
x2[n + 31] = (x2[n + 3] + x2[n + 2] + +x2[n+1] + x2[n]) & 0x1;
|
||||
}
|
||||
|
||||
for (n = 0; n < q->len; n++) {
|
||||
for (n = 0; n < len; n++) {
|
||||
q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1;
|
||||
}
|
||||
|
||||
free(x1);
|
||||
free(x2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
|
||||
if (srslte_sequence_init(q, len)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->len = len;
|
||||
srslte_sequence_set_LTE_pr(q, seed);
|
||||
q->cur_len = len;
|
||||
srslte_sequence_set_LTE_pr(q, len, seed);
|
||||
srslte_bit_pack_vector(q->c, q->c_bytes, len);
|
||||
for (int i=0;i<len;i++) {
|
||||
q->c_float[i] = (1-2*q->c[i]);
|
||||
|
@ -90,17 +144,8 @@ int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
|
|||
}
|
||||
|
||||
int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) {
|
||||
if (q->c && (q->len != len)) {
|
||||
free(q->c);
|
||||
if (q->c_bytes) {
|
||||
free(q->c_bytes);
|
||||
}
|
||||
if (q->c_float) {
|
||||
free(q->c_float);
|
||||
}
|
||||
if (q->c_short) {
|
||||
free(q->c_short);
|
||||
}
|
||||
if (q->c && len > q->max_len) {
|
||||
srslte_sequence_free(q);
|
||||
}
|
||||
if (!q->c) {
|
||||
q->c = srslte_vec_malloc(len * sizeof(uint8_t));
|
||||
|
@ -119,7 +164,7 @@ int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) {
|
|||
if (!q->c_short) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
q->len = len;
|
||||
q->max_len = len;
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <complex.h>
|
||||
#include <fftw3.h>
|
||||
#include <string.h>
|
||||
#include <srslte/srslte.h>
|
||||
|
||||
#include "srslte/phy/dft/dft.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
@ -38,14 +39,27 @@
|
|||
|
||||
#define FFTW_WISDOM_FILE ".fftw_wisdom"
|
||||
|
||||
#ifdef FFTW_WISDOM_FILE
|
||||
#define FFTW_TYPE FFTW_MEASURE
|
||||
#else
|
||||
#define FFTW_TYPE 0
|
||||
#endif
|
||||
|
||||
|
||||
void srslte_dft_load() {
|
||||
#ifdef FFTW_WISDOM_FILE
|
||||
fftwf_import_wisdom_from_filename(FFTW_WISDOM_FILE);
|
||||
#else
|
||||
printf("Warning: FFTW Wisdom file not defined\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void srslte_dft_exit() {
|
||||
#ifdef FFTW_WISDOM_FILE
|
||||
if (!fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE)) {
|
||||
fprintf(stderr, "Error saving FFTW wisdom to file %s\n", FFTW_WISDOM_FILE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir,
|
||||
|
@ -58,19 +72,50 @@ int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_di
|
|||
return 0;
|
||||
}
|
||||
|
||||
int srslte_dft_replan(srslte_dft_plan_t *plan, const int new_dft_points) {
|
||||
if (new_dft_points <= plan->init_size) {
|
||||
if(plan->mode == SRSLTE_DFT_COMPLEX){
|
||||
return srslte_dft_replan_c(plan,new_dft_points);
|
||||
} else {
|
||||
return srslte_dft_replan_r(plan,new_dft_points);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "DFT: Error calling replan: new_dft_points (%d) must be lower or equal "
|
||||
"dft_size passed initially (%d)\n", new_dft_points, plan->init_size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void allocate(srslte_dft_plan_t *plan, int size_in, int size_out, int len) {
|
||||
plan->in = fftwf_malloc(size_in*len);
|
||||
plan->out = fftwf_malloc(size_out*len);
|
||||
}
|
||||
|
||||
int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) {
|
||||
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
|
||||
if (plan->p) {
|
||||
fftwf_destroy_plan(plan->p);
|
||||
plan->p = NULL;
|
||||
}
|
||||
plan->p = fftwf_plan_dft_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
|
||||
if (!plan->p) {
|
||||
return -1;
|
||||
}
|
||||
plan->size = new_dft_points;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
|
||||
allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points);
|
||||
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
|
||||
plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_MEASURE);
|
||||
plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
|
||||
if (!plan->p) {
|
||||
return -1;
|
||||
}
|
||||
plan->size = dft_points;
|
||||
plan->init_size = plan->size;
|
||||
plan->mode = SRSLTE_DFT_COMPLEX;
|
||||
plan->dir = dir;
|
||||
plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false;
|
||||
|
@ -82,14 +127,29 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) {
|
||||
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
|
||||
if (plan->p) {
|
||||
fftwf_destroy_plan(plan->p);
|
||||
plan->p = NULL;
|
||||
}
|
||||
plan->p = fftwf_plan_r2r_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
|
||||
if (!plan->p) {
|
||||
return -1;
|
||||
}
|
||||
plan->size = new_dft_points;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
|
||||
allocate(plan,sizeof(float),sizeof(float), dft_points);
|
||||
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
|
||||
plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_MEASURE);
|
||||
plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
|
||||
if (!plan->p) {
|
||||
return -1;
|
||||
}
|
||||
plan->size = dft_points;
|
||||
plan->init_size = plan->size;
|
||||
plan->mode = SRSLTE_REAL;
|
||||
plan->dir = dir;
|
||||
plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false;
|
||||
|
|
|
@ -40,37 +40,42 @@
|
|||
#include "srslte/phy/dft/dft_precoding.h"
|
||||
|
||||
/* Create DFT plans for transform precoding */
|
||||
int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb)
|
||||
|
||||
int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb, bool is_tx)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
bzero(q, sizeof(srslte_dft_precoding_t));
|
||||
|
||||
|
||||
if (max_prb <= SRSLTE_MAX_PRB) {
|
||||
ret = SRSLTE_ERROR;
|
||||
ret = SRSLTE_ERROR;
|
||||
for (uint32_t i=1;i<=max_prb;i++) {
|
||||
if(srslte_dft_precoding_valid_prb(i)) {
|
||||
if(srslte_dft_precoding_valid_prb(i)) {
|
||||
DEBUG("Initiating DFT precoding plan for %d PRBs\n", i);
|
||||
if (srslte_dft_plan_c(&q->dft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_FORWARD)) {
|
||||
if (srslte_dft_plan_c(&q->dft_plan[i], i*SRSLTE_NRE, is_tx?SRSLTE_DFT_FORWARD:SRSLTE_DFT_BACKWARD)) {
|
||||
fprintf(stderr, "Error: Creating DFT plan %d\n",i);
|
||||
goto clean_exit;
|
||||
}
|
||||
srslte_dft_plan_set_norm(&q->dft_plan[i], true);
|
||||
if (srslte_dft_plan_c(&q->idft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_BACKWARD)) {
|
||||
fprintf(stderr, "Error: Creating DFT plan %d\n",i);
|
||||
goto clean_exit;
|
||||
}
|
||||
srslte_dft_plan_set_norm(&q->idft_plan[i], true);
|
||||
}
|
||||
}
|
||||
q->max_prb = max_prb;
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
clean_exit:
|
||||
clean_exit:
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
srslte_dft_precoding_free(q);
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srslte_dft_precoding_init_rx(srslte_dft_precoding_t *q, uint32_t max_prb)
|
||||
{
|
||||
return srslte_dft_precoding_init(q, max_prb, false);
|
||||
}
|
||||
|
||||
int srslte_dft_precoding_init_tx(srslte_dft_precoding_t *q, uint32_t max_prb) {
|
||||
return srslte_dft_precoding_init(q, max_prb, true);
|
||||
}
|
||||
|
||||
/* Free DFT plans for transform precoding */
|
||||
|
@ -79,7 +84,6 @@ void srslte_dft_precoding_free(srslte_dft_precoding_t *q)
|
|||
for (uint32_t i=1;i<=q->max_prb;i++) {
|
||||
if(srslte_dft_precoding_valid_prb(i)) {
|
||||
srslte_dft_plan_free(&q->dft_plan[i]);
|
||||
srslte_dft_plan_free(&q->idft_plan[i]);
|
||||
}
|
||||
}
|
||||
bzero(q, sizeof(srslte_dft_precoding_t));
|
||||
|
@ -98,7 +102,7 @@ bool srslte_dft_precoding_valid_prb(uint32_t nof_prb) {
|
|||
}
|
||||
|
||||
int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
|
||||
uint32_t nof_prb, uint32_t nof_symbols)
|
||||
uint32_t nof_prb, uint32_t nof_symbols)
|
||||
{
|
||||
|
||||
if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) {
|
||||
|
@ -112,19 +116,3 @@ int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
|
|||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_dft_predecoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
|
||||
uint32_t nof_prb, uint32_t nof_symbols)
|
||||
{
|
||||
if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) {
|
||||
fprintf(stderr, "Error invalid number of PRB (%d)\n", nof_prb);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
for (uint32_t i=0;i<nof_symbols;i++) {
|
||||
srslte_dft_run_c(&q->idft_plan[nof_prb], &input[i*SRSLTE_NRE*nof_prb], &output[i*SRSLTE_NRE*nof_prb]);
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
#include <srslte/srslte.h>
|
||||
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
#include "srslte/phy/dft/dft.h"
|
||||
|
@ -36,7 +37,13 @@
|
|||
#include "srslte/phy/utils/debug.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
||||
|
||||
int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) {
|
||||
return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM);
|
||||
}
|
||||
|
||||
|
||||
int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) {
|
||||
|
||||
if (srslte_dft_plan_c(&q->fft_plan, symbol_sz, dir)) {
|
||||
fprintf(stderr, "Error: Creating DFT plan\n");
|
||||
|
@ -48,14 +55,20 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p
|
|||
return -1;
|
||||
}
|
||||
|
||||
q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz));
|
||||
if (!q->shift_buffer) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
srslte_dft_plan_set_mirror(&q->fft_plan, true);
|
||||
srslte_dft_plan_set_dc(&q->fft_plan, true);
|
||||
|
||||
q->symbol_sz = (uint32_t) symbol_sz;
|
||||
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
|
||||
q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT);
|
||||
q->cp = cp;
|
||||
q->freq_shift = false;
|
||||
q->shift_buffer = NULL;
|
||||
q->nof_re = nof_prb * SRSLTE_NRE;
|
||||
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
|
||||
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
|
||||
|
@ -63,6 +76,42 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p
|
|||
DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n",
|
||||
dir==SRSLTE_DFT_FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols,
|
||||
q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards);
|
||||
|
||||
// MBSFN logic
|
||||
if (sf_type == SRSLTE_SF_MBSFN) {
|
||||
q->mbsfn_subframe = true;
|
||||
q->non_mbsfn_region = 2; // default set to 2
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void srslte_ofdm_set_non_mbsfn_region(srslte_ofdm_t *q, uint8_t non_mbsfn_region)
|
||||
{
|
||||
q->non_mbsfn_region = non_mbsfn_region;
|
||||
}
|
||||
|
||||
int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb) {
|
||||
|
||||
if (srslte_dft_replan_c(&q->fft_plan, symbol_sz)) {
|
||||
fprintf(stderr, "Error: Creating DFT plan\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
q->symbol_sz = (uint32_t) symbol_sz;
|
||||
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
|
||||
q->cp = cp;
|
||||
q->nof_re = nof_prb * SRSLTE_NRE;
|
||||
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
|
||||
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
|
||||
|
||||
if (q->freq_shift) {
|
||||
srslte_ofdm_set_freq_shift(q, q->freq_shift_f);
|
||||
}
|
||||
|
||||
DEBUG("Replan symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n",
|
||||
q->symbol_sz, q->nof_symbols,
|
||||
q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
@ -78,30 +127,39 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) {
|
|||
bzero(q, sizeof(srslte_ofdm_t));
|
||||
}
|
||||
|
||||
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
|
||||
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
|
||||
int symbol_sz = srslte_symbol_sz(max_prb);
|
||||
if (symbol_sz < 0) {
|
||||
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
|
||||
return -1;
|
||||
}
|
||||
q->max_prb = max_prb;
|
||||
return srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_FORWARD);
|
||||
}
|
||||
|
||||
int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb)
|
||||
{
|
||||
int symbol_sz = srslte_symbol_sz(nof_prb);
|
||||
if (symbol_sz < 0) {
|
||||
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
|
||||
return -1;
|
||||
}
|
||||
return srslte_ofdm_init_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD);
|
||||
return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN);
|
||||
}
|
||||
|
||||
void srslte_ofdm_rx_free(srslte_ofdm_t *q) {
|
||||
srslte_ofdm_free_(q);
|
||||
}
|
||||
|
||||
int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
|
||||
int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
|
||||
uint32_t i;
|
||||
int ret;
|
||||
|
||||
int symbol_sz = srslte_symbol_sz(nof_prb);
|
||||
int symbol_sz = srslte_symbol_sz(max_prb);
|
||||
if (symbol_sz < 0) {
|
||||
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
|
||||
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
|
||||
return -1;
|
||||
}
|
||||
q->max_prb = max_prb;
|
||||
ret = srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD);
|
||||
|
||||
ret = srslte_ofdm_init_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD);
|
||||
|
||||
if (ret == SRSLTE_SUCCESS) {
|
||||
srslte_dft_plan_set_norm(&q->fft_plan, false);
|
||||
|
@ -115,16 +173,81 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb)
|
||||
{
|
||||
uint32_t i;
|
||||
int ret;
|
||||
|
||||
int symbol_sz = srslte_symbol_sz(nof_prb);
|
||||
if (symbol_sz < 0) {
|
||||
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN);
|
||||
|
||||
if (ret == SRSLTE_SUCCESS) {
|
||||
srslte_dft_plan_set_norm(&q->fft_plan, false);
|
||||
|
||||
/* set now zeros at CP */
|
||||
for (i=0;i<q->nof_symbols;i++) {
|
||||
bzero(q->tmp, q->nof_guards * sizeof(cf_t));
|
||||
bzero(&q->tmp[q->nof_re + q->nof_guards], q->nof_guards * sizeof(cf_t));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
|
||||
if (nof_prb <= q->max_prb) {
|
||||
int symbol_sz = srslte_symbol_sz(nof_prb);
|
||||
if (symbol_sz < 0) {
|
||||
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
|
||||
return -1;
|
||||
}
|
||||
return srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb);
|
||||
} else {
|
||||
fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
|
||||
uint32_t i;
|
||||
int ret;
|
||||
|
||||
if (nof_prb <= q->max_prb) {
|
||||
int symbol_sz = srslte_symbol_sz(nof_prb);
|
||||
if (symbol_sz < 0) {
|
||||
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb);
|
||||
|
||||
if (ret == SRSLTE_SUCCESS) {
|
||||
/* set now zeros at CP */
|
||||
for (i=0;i<q->nof_symbols;i++) {
|
||||
bzero(q->tmp, q->nof_guards * sizeof(cf_t));
|
||||
bzero(&q->tmp[q->nof_re + q->nof_guards], q->nof_guards * sizeof(cf_t));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void srslte_ofdm_rx_free(srslte_ofdm_t *q) {
|
||||
srslte_ofdm_free_(q);
|
||||
}
|
||||
/* Shifts the signal after the iFFT or before the FFT.
|
||||
* Freq_shift is relative to inter-carrier spacing.
|
||||
* Caution: This function shall not be called during run-time
|
||||
*/
|
||||
int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) {
|
||||
q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(q->symbol_sz));
|
||||
if (!q->shift_buffer) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
cf_t *ptr = q->shift_buffer;
|
||||
for (uint32_t n=0;n<2;n++) {
|
||||
for (uint32_t i=0;i<q->nof_symbols;i++) {
|
||||
|
@ -140,7 +263,7 @@ int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) {
|
|||
srslte_dft_plan_set_dc(&q->fft_plan, false);
|
||||
|
||||
q->freq_shift = true;
|
||||
|
||||
q->freq_shift_f = freq_shift;
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -162,6 +285,23 @@ void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
|
|||
}
|
||||
}
|
||||
|
||||
void srslte_ofdm_rx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < q->nof_symbols_mbsfn; i++){
|
||||
if(i == q->non_mbsfn_region) {
|
||||
input += SRSLTE_NON_MBSFN_REGION_GUARD_LENGTH(q->non_mbsfn_region,q->symbol_sz);
|
||||
}
|
||||
input += (i>=q->non_mbsfn_region)?SRSLTE_CP_LEN_EXT(q->symbol_sz):SRSLTE_CP_LEN_NORM(i, q->symbol_sz);
|
||||
srslte_dft_run_c(&q->fft_plan, input, q->tmp);
|
||||
memcpy(output, &q->tmp[q->nof_guards], q->nof_re * sizeof(cf_t));
|
||||
input += q->symbol_sz;
|
||||
output += q->nof_re;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void srslte_ofdm_rx_slot_zerocopy(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
|
||||
uint32_t i;
|
||||
for (i=0;i<q->nof_symbols;i++) {
|
||||
|
@ -179,8 +319,14 @@ void srslte_ofdm_rx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
|
|||
if (q->freq_shift) {
|
||||
srslte_vec_prod_ccc(input, q->shift_buffer, input, 2*q->slot_sz);
|
||||
}
|
||||
for (n=0;n<2;n++) {
|
||||
srslte_ofdm_rx_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]);
|
||||
if(!q->mbsfn_subframe){
|
||||
for (n=0;n<2;n++) {
|
||||
srslte_ofdm_rx_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
srslte_ofdm_rx_slot_mbsfn(q, &input[0*q->slot_sz], &output[0*q->nof_re*q->nof_symbols]);
|
||||
srslte_ofdm_rx_slot(q, &input[1*q->slot_sz], &output[1*q->nof_re*q->nof_symbols]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,16 +346,43 @@ void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
|
|||
}
|
||||
}
|
||||
|
||||
void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output)
|
||||
{
|
||||
uint32_t i, cp_len;
|
||||
|
||||
for(i=0;i<q->nof_symbols_mbsfn;i++) {
|
||||
cp_len = ( i>(q->non_mbsfn_region-1) )?SRSLTE_CP_LEN_EXT(q->symbol_sz):SRSLTE_CP_LEN_NORM(i, q->symbol_sz);
|
||||
memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t));
|
||||
srslte_dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]);
|
||||
input += q->nof_re;
|
||||
/* add CP */
|
||||
memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t));
|
||||
output += q->symbol_sz + cp_len;
|
||||
|
||||
/*skip the small section between the non mbms region and the mbms region*/
|
||||
if(i == (q->non_mbsfn_region - 1))
|
||||
output += SRSLTE_NON_MBSFN_REGION_GUARD_LENGTH(q->non_mbsfn_region,q->symbol_sz);
|
||||
}
|
||||
}
|
||||
|
||||
void srslte_ofdm_set_normalize(srslte_ofdm_t *q, bool normalize_enable) {
|
||||
srslte_dft_plan_set_norm(&q->fft_plan, normalize_enable);
|
||||
}
|
||||
|
||||
void srslte_ofdm_tx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
|
||||
void srslte_ofdm_tx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output)
|
||||
{
|
||||
uint32_t n;
|
||||
for (n=0;n<2;n++) {
|
||||
srslte_ofdm_tx_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]);
|
||||
if(!q->mbsfn_subframe){
|
||||
for (n=0;n<2;n++) {
|
||||
srslte_ofdm_tx_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
srslte_ofdm_tx_slot_mbsfn(q, &input[0*q->nof_re*q->nof_symbols], &output[0*q->slot_sz]);
|
||||
srslte_ofdm_tx_slot(q, &input[1*q->nof_re*q->nof_symbols], &output[1*q->slot_sz]);
|
||||
}
|
||||
if (q->freq_shift) {
|
||||
srslte_vec_prod_ccc(output, q->shift_buffer, output, 2*q->slot_sz);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <complex.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
#include <srslte/srslte.h>
|
||||
|
||||
|
||||
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
|
||||
|
@ -39,78 +41,67 @@
|
|||
|
||||
#define SRSLTE_ENB_RF_AMP 0.1
|
||||
|
||||
int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell)
|
||||
int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
bzero(q, sizeof(srslte_enb_dl_t));
|
||||
|
||||
q->cell = cell;
|
||||
q->cfi = 3;
|
||||
q->cfi = 3;
|
||||
q->tx_amp = SRSLTE_ENB_RF_AMP;
|
||||
|
||||
if (srslte_ofdm_tx_init(&q->ifft, q->cell.cp, q->cell.nof_prb)) {
|
||||
if (srslte_ofdm_tx_init(&q->ifft, SRSLTE_CP_NORM, max_prb)) {
|
||||
fprintf(stderr, "Error initiating FFT\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
srslte_ofdm_set_normalize(&q->ifft, true);
|
||||
|
||||
if (srslte_regs_init(&q->regs, q->cell)) {
|
||||
fprintf(stderr, "Error initiating REGs\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
if (srslte_pbch_init(&q->pbch, q->cell)) {
|
||||
if (srslte_pbch_init(&q->pbch)) {
|
||||
fprintf(stderr, "Error creating PBCH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
if (srslte_pcfich_init(&q->pcfich, &q->regs, q->cell)) {
|
||||
if (srslte_pcfich_init(&q->pcfich, 0)) {
|
||||
fprintf(stderr, "Error creating PCFICH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
if (srslte_phich_init(&q->phich, &q->regs, q->cell)) {
|
||||
if (srslte_phich_init(&q->phich, 0)) {
|
||||
fprintf(stderr, "Error creating PHICH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) {
|
||||
if (srslte_pdcch_init_enb(&q->pdcch, max_prb)) {
|
||||
fprintf(stderr, "Error creating PDCCH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_pdsch_init_tx(&q->pdsch, q->cell)) {
|
||||
if (srslte_pdsch_init_enb(&q->pdsch, max_prb)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_refsignal_cs_init(&q->csr_signal, q->cell)) {
|
||||
if (srslte_refsignal_cs_init(&q->csr_signal, max_prb)) {
|
||||
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
for (int i=0;i<q->cell.nof_ports;i++) {
|
||||
q->sf_symbols[i] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
|
||||
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
q->sf_symbols[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
|
||||
if (!q->sf_symbols[i]) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->slot1_symbols[i] = &q->sf_symbols[i][CURRENT_SLOTLEN_RE];
|
||||
q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)];
|
||||
}
|
||||
|
||||
/* Generate PSS/SSS signals */
|
||||
srslte_pss_generate(q->pss_signal, cell.id%3);
|
||||
srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id);
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
|
||||
cell.id, cell.nof_ports, cell.nof_prb);
|
||||
fprintf(stderr, "Invalid parameters\n");
|
||||
}
|
||||
|
||||
clean_exit:
|
||||
|
@ -125,12 +116,13 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q)
|
|||
if (q) {
|
||||
srslte_ofdm_tx_free(&q->ifft);
|
||||
srslte_regs_free(&q->regs);
|
||||
srslte_pbch_free(&q->pbch);
|
||||
srslte_pcfich_free(&q->pcfich);
|
||||
srslte_phich_free(&q->phich);
|
||||
srslte_pdcch_free(&q->pdcch);
|
||||
srslte_pdsch_free(&q->pdsch);
|
||||
|
||||
srslte_refsignal_cs_free(&q->csr_signal);
|
||||
srslte_refsignal_free(&q->csr_signal);
|
||||
|
||||
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
if (q->sf_symbols[i]) {
|
||||
|
@ -141,6 +133,71 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q)
|
|||
}
|
||||
}
|
||||
|
||||
int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
srslte_enb_dl_set_cfi(q, 3);
|
||||
q->tx_amp = SRSLTE_ENB_RF_AMP;
|
||||
|
||||
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
|
||||
if (q->cell.nof_prb != 0) {
|
||||
srslte_regs_free(&q->regs);
|
||||
}
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
if (srslte_regs_init(&q->regs, q->cell)) {
|
||||
fprintf(stderr, "Error resizing REGs\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_ofdm_rx_set_prb(&q->ifft, q->cell.cp, q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating FFT\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_pbch_set_cell(&q->pbch, q->cell)) {
|
||||
fprintf(stderr, "Error creating PBCH object\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_pcfich_set_cell(&q->pcfich, &q->regs, q->cell)) {
|
||||
fprintf(stderr, "Error creating PCFICH object\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_phich_set_cell(&q->phich, &q->regs, q->cell)) {
|
||||
fprintf(stderr, "Error creating PHICH object\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_pdcch_set_cell(&q->pdcch, &q->regs, q->cell)) {
|
||||
fprintf(stderr, "Error creating PDCCH object\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_refsignal_cs_set_cell(&q->csr_signal, q->cell)) {
|
||||
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
/* Generate PSS/SSS signals */
|
||||
srslte_pss_generate(q->pss_signal, cell.id%3);
|
||||
srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id);
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
|
||||
cell.id, cell.nof_ports, cell.nof_prb);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp)
|
||||
{
|
||||
q->tx_amp = amp;
|
||||
|
@ -263,11 +320,11 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant,
|
|||
}
|
||||
|
||||
int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
|
||||
uint16_t rnti, uint32_t rv_idx, uint32_t sf_idx,
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS])
|
||||
uint16_t rnti, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx,
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pmi)
|
||||
{
|
||||
/* Configure pdsch_cfg parameters */
|
||||
if (srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx)) {
|
||||
if (srslte_pdsch_cfg_mimo(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx, mimo_type, pmi)) {
|
||||
fprintf(stderr, "Error configuring PDSCH\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
@ -279,3 +336,33 @@ int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srs
|
|||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void srslte_enb_dl_save_signal(srslte_enb_dl_t *q, srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint32_t tti, uint32_t rv_idx, uint16_t rnti, uint32_t cfi)
|
||||
{
|
||||
char tmpstr[64];
|
||||
|
||||
snprintf(tmpstr,64,"output/sf_symbols_%d",tti);
|
||||
srslte_vec_save_file(tmpstr, q->sf_symbols[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
|
||||
snprintf(tmpstr,64,"output/e_%d",tti);
|
||||
srslte_bit_unpack_vector(q->pdsch.e[0], q->tmp, q->pdsch_cfg.nbits[0].nof_bits);
|
||||
srslte_vec_save_file(tmpstr, q->tmp, q->pdsch_cfg.nbits[0].nof_bits*sizeof(uint8_t));
|
||||
|
||||
/*
|
||||
int cb_len = q->pdsch_cfg.cb_segm[0].K1;
|
||||
for (int i=0;i<q->pdsch_cfg.cb_segm[0].C;i++) {
|
||||
snprintf(tmpstr,64,"output/rmout_%d_%d",i,tti);
|
||||
srslte_bit_unpack_vector(softbuffer->buffer_b[i], q->tmp, (3*cb_len+12));
|
||||
srslte_vec_save_file(tmpstr, q->tmp, (3*cb_len+12)*sizeof(uint8_t));
|
||||
}*/
|
||||
|
||||
snprintf(tmpstr,64,"output/data_%d",tti);
|
||||
srslte_bit_unpack_vector(data, q->tmp, q->pdsch_cfg.grant.mcs[0].tbs);
|
||||
srslte_vec_save_file(tmpstr, q->tmp, q->pdsch_cfg.grant.mcs[0].tbs*sizeof(uint8_t));
|
||||
|
||||
//printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, tbs=%d, rv=%d, rnti=0x%x\n", tti, tti%10, cfi,
|
||||
// q->pdsch_cfg.grant.mcs[0].idx, q->pdsch_cfg.grant.mcs[0].tbs, rv_idx, rnti);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,78 +39,54 @@
|
|||
|
||||
#define MAX_CANDIDATES 16
|
||||
|
||||
int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
|
||||
srslte_prach_cfg_t *prach_cfg,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg)
|
||||
int srslte_enb_ul_init(srslte_enb_ul_t *q,
|
||||
uint32_t max_prb)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
bzero(q, sizeof(srslte_enb_ul_t));
|
||||
|
||||
q->cell = cell;
|
||||
|
||||
if (hopping_cfg) {
|
||||
memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t));
|
||||
}
|
||||
|
||||
q->users = calloc(sizeof(srslte_enb_ul_user_t*), SRSLTE_SIRNTI);
|
||||
q->users = calloc(sizeof(srslte_enb_ul_user_t*), (1+SRSLTE_SIRNTI));
|
||||
if (!q->users) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
|
||||
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
|
||||
fprintf(stderr, "Error initiating FFT\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
srslte_ofdm_set_normalize(&q->fft, false);
|
||||
srslte_ofdm_set_freq_shift(&q->fft, -0.5);
|
||||
|
||||
if (srslte_pucch_init(&q->pucch, q->cell)) {
|
||||
if (srslte_pucch_init(&q->pucch)) {
|
||||
fprintf(stderr, "Error creating PUCCH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_pusch_init(&q->pusch, q->cell)) {
|
||||
if (srslte_pusch_init_enb(&q->pusch, max_prb)) {
|
||||
fprintf(stderr, "Error creating PUSCH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (prach_cfg) {
|
||||
if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating PRACH\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
srslte_prach_set_detect_factor(&q->prach, 60);
|
||||
}
|
||||
|
||||
|
||||
srslte_pucch_set_threshold(&q->pucch, 0.8);
|
||||
|
||||
if (srslte_chest_ul_init(&q->chest, cell)) {
|
||||
|
||||
if (srslte_chest_ul_init(&q->chest, max_prb)) {
|
||||
fprintf(stderr, "Error initiating channel estimator\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Configure common PUCCH configuration
|
||||
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en);
|
||||
|
||||
// SRS is a dedicated configuration
|
||||
srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL);
|
||||
|
||||
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
|
||||
|
||||
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
|
||||
if (!q->sf_symbols) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
q->ce = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
|
||||
q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
|
||||
if (!q->ce) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
|
@ -119,8 +95,7 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
|
|||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
|
||||
cell.id, cell.nof_ports, cell.nof_prb);
|
||||
fprintf(stderr, "Invalid parameters\n");
|
||||
}
|
||||
|
||||
clean_exit:
|
||||
|
@ -135,7 +110,7 @@ void srslte_enb_ul_free(srslte_enb_ul_t *q)
|
|||
if (q) {
|
||||
|
||||
if (q->users) {
|
||||
for (int i=0;i<SRSLTE_SIRNTI;i++) {
|
||||
for (int i=0;i<=SRSLTE_SIRNTI;i++) {
|
||||
if (q->users[i]) {
|
||||
free(q->users[i]);
|
||||
}
|
||||
|
@ -158,11 +133,73 @@ void srslte_enb_ul_free(srslte_enb_ul_t *q)
|
|||
}
|
||||
}
|
||||
|
||||
int srslte_enb_ul_set_cell(srslte_enb_ul_t *q, srslte_cell_t cell,
|
||||
srslte_prach_cfg_t *prach_cfg,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
|
||||
if (hopping_cfg) {
|
||||
memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t));
|
||||
}
|
||||
|
||||
if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating FFT\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_pucch_set_cell(&q->pucch, q->cell)) {
|
||||
fprintf(stderr, "Error creating PUCCH object\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_pusch_set_cell(&q->pusch, q->cell)) {
|
||||
fprintf(stderr, "Error creating PUSCH object\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (prach_cfg) {
|
||||
if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating PRACH\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_prach_set_detect_factor(&q->prach, 60);
|
||||
}
|
||||
|
||||
if (srslte_chest_ul_set_cell(&q->chest, cell)) {
|
||||
fprintf(stderr, "Error initiating channel estimator\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Configure common PUCCH configuration
|
||||
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en);
|
||||
|
||||
// SRS is a dedicated configuration
|
||||
srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL);
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
|
||||
cell.id, cell.nof_ports, cell.nof_prb);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint16_t rnti)
|
||||
{
|
||||
if (!q->users[rnti]) {
|
||||
q->users[rnti] = malloc(sizeof(srslte_enb_ul_user_t));
|
||||
|
||||
q->users[rnti] = calloc(1, sizeof(srslte_enb_ul_user_t));
|
||||
|
||||
if (srslte_pucch_set_crnti(&q->pucch, rnti)) {
|
||||
fprintf(stderr, "Error setting PUCCH rnti\n");
|
||||
return -1;
|
||||
|
@ -183,7 +220,7 @@ void srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, uint16_t rnti)
|
|||
if (q->users[rnti]) {
|
||||
free(q->users[rnti]);
|
||||
q->users[rnti] = NULL;
|
||||
srslte_pusch_clear_rnti(&q->pusch, rnti);
|
||||
srslte_pusch_free_rnti(&q->pusch, rnti);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ int main(int argc, char **argv) {
|
|||
float *llr;
|
||||
short *llr_s;
|
||||
uint8_t *llr_c;
|
||||
uint8_t *data_tx, *data_rx, *data_rx_bytes[SRSLTE_TDEC_NPAR], *symbols;
|
||||
uint8_t *data_tx, *data_rx, *data_rx_bytes[SRSLTE_TDEC_MAX_NPAR], *symbols;
|
||||
uint32_t i, j;
|
||||
float var[SNR_POINTS];
|
||||
uint32_t snr_points;
|
||||
|
@ -159,7 +159,7 @@ int main(int argc, char **argv) {
|
|||
perror("malloc");
|
||||
exit(-1);
|
||||
}
|
||||
for (int cb=0;cb<SRSLTE_TDEC_NPAR;cb++) {
|
||||
for (int cb=0;cb<SRSLTE_TDEC_MAX_NPAR;cb++) {
|
||||
data_rx_bytes[cb] = srslte_vec_malloc(frame_length * sizeof(uint8_t));
|
||||
if (!data_rx_bytes[cb]) {
|
||||
perror("malloc");
|
||||
|
@ -254,10 +254,10 @@ int main(int argc, char **argv) {
|
|||
t = nof_iterations;
|
||||
}
|
||||
|
||||
int16_t *input[SRSLTE_TDEC_NPAR];
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR];
|
||||
int16_t *input[SRSLTE_TDEC_MAX_NPAR];
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR];
|
||||
|
||||
for (int n=0;n<SRSLTE_TDEC_NPAR;n++) {
|
||||
for (int n=0;n<SRSLTE_TDEC_MAX_NPAR;n++) {
|
||||
if (n < nof_cb) {
|
||||
input[n] = llr_s;
|
||||
} else {
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
int srslte_tdec_init(srslte_tdec_t * h, uint32_t max_long_cb) {
|
||||
#ifdef LV_HAVE_SSE
|
||||
return srslte_tdec_simd_init(&h->tdec_simd, SRSLTE_TDEC_NPAR, max_long_cb);
|
||||
return srslte_tdec_simd_init(&h->tdec_simd, SRSLTE_TDEC_MAX_NPAR, max_long_cb);
|
||||
#else
|
||||
h->input_conv = srslte_vec_malloc(sizeof(float) * (3*max_long_cb+12));
|
||||
if (!h->input_conv) {
|
||||
|
@ -91,7 +91,7 @@ int srslte_tdec_get_nof_iterations_cb(srslte_tdec_t * h, uint32_t cb_idx)
|
|||
#endif
|
||||
}
|
||||
|
||||
void srslte_tdec_iteration_par(srslte_tdec_t * h, int16_t* input[SRSLTE_TDEC_NPAR], uint32_t long_cb) {
|
||||
void srslte_tdec_iteration_par(srslte_tdec_t * h, int16_t* input[SRSLTE_TDEC_MAX_NPAR], uint32_t long_cb) {
|
||||
#ifdef LV_HAVE_SSE
|
||||
srslte_tdec_simd_iteration(&h->tdec_simd, input, long_cb);
|
||||
#else
|
||||
|
@ -101,12 +101,12 @@ void srslte_tdec_iteration_par(srslte_tdec_t * h, int16_t* input[SRSLTE_TDEC_NPA
|
|||
}
|
||||
|
||||
void srslte_tdec_iteration(srslte_tdec_t * h, int16_t* input, uint32_t long_cb) {
|
||||
int16_t *input_par[SRSLTE_TDEC_NPAR];
|
||||
int16_t *input_par[SRSLTE_TDEC_MAX_NPAR];
|
||||
input_par[0] = input;
|
||||
return srslte_tdec_iteration_par(h, input_par, long_cb);
|
||||
}
|
||||
|
||||
void srslte_tdec_decision_par(srslte_tdec_t * h, uint8_t *output[SRSLTE_TDEC_NPAR], uint32_t long_cb) {
|
||||
void srslte_tdec_decision_par(srslte_tdec_t * h, uint8_t *output[SRSLTE_TDEC_MAX_NPAR], uint32_t long_cb) {
|
||||
#ifdef LV_HAVE_SSE
|
||||
return srslte_tdec_simd_decision(&h->tdec_simd, output, long_cb);
|
||||
#else
|
||||
|
@ -114,13 +114,21 @@ void srslte_tdec_decision_par(srslte_tdec_t * h, uint8_t *output[SRSLTE_TDEC_NPA
|
|||
#endif
|
||||
}
|
||||
|
||||
uint32_t srslte_tdec_get_nof_parallel(srslte_tdec_t *h) {
|
||||
#ifdef LV_HAVE_AVX2
|
||||
return 2;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void srslte_tdec_decision(srslte_tdec_t * h, uint8_t *output, uint32_t long_cb) {
|
||||
uint8_t *output_par[SRSLTE_TDEC_NPAR];
|
||||
uint8_t *output_par[SRSLTE_TDEC_MAX_NPAR];
|
||||
output_par[0] = output;
|
||||
srslte_tdec_decision_par(h, output_par, long_cb);
|
||||
}
|
||||
|
||||
void srslte_tdec_decision_byte_par(srslte_tdec_t * h, uint8_t *output[SRSLTE_TDEC_NPAR], uint32_t long_cb) {
|
||||
void srslte_tdec_decision_byte_par(srslte_tdec_t * h, uint8_t *output[SRSLTE_TDEC_MAX_NPAR], uint32_t long_cb) {
|
||||
#ifdef LV_HAVE_SSE
|
||||
srslte_tdec_simd_decision_byte(&h->tdec_simd, output, long_cb);
|
||||
#else
|
||||
|
@ -137,13 +145,13 @@ void srslte_tdec_decision_byte_par_cb(srslte_tdec_t * h, uint8_t *output, uint32
|
|||
}
|
||||
|
||||
void srslte_tdec_decision_byte(srslte_tdec_t * h, uint8_t *output, uint32_t long_cb) {
|
||||
uint8_t *output_par[SRSLTE_TDEC_NPAR];
|
||||
uint8_t *output_par[SRSLTE_TDEC_MAX_NPAR];
|
||||
output_par[0] = output;
|
||||
srslte_tdec_decision_byte_par(h, output_par, long_cb);
|
||||
}
|
||||
|
||||
int srslte_tdec_run_all_par(srslte_tdec_t * h, int16_t * input[SRSLTE_TDEC_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
int srslte_tdec_run_all_par(srslte_tdec_t * h, int16_t * input[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_iterations, uint32_t long_cb) {
|
||||
#ifdef LV_HAVE_SSE
|
||||
return srslte_tdec_simd_run_all(&h->tdec_simd, input, output, nof_iterations, long_cb);
|
||||
|
@ -155,9 +163,9 @@ int srslte_tdec_run_all_par(srslte_tdec_t * h, int16_t * input[SRSLTE_TDEC_NPAR]
|
|||
|
||||
int srslte_tdec_run_all(srslte_tdec_t * h, int16_t * input, uint8_t *output, uint32_t nof_iterations, uint32_t long_cb)
|
||||
{
|
||||
uint8_t *output_par[SRSLTE_TDEC_NPAR];
|
||||
uint8_t *output_par[SRSLTE_TDEC_MAX_NPAR];
|
||||
output_par[0] = output;
|
||||
int16_t *input_par[SRSLTE_TDEC_NPAR];
|
||||
int16_t *input_par[SRSLTE_TDEC_MAX_NPAR];
|
||||
input_par[0] = input;
|
||||
|
||||
return srslte_tdec_run_all_par(h, input_par, output_par, nof_iterations, long_cb);
|
||||
|
|
|
@ -81,7 +81,7 @@ static inline int16_t hMax1(__m256i masked_value)
|
|||
}
|
||||
|
||||
/* Computes beta values */
|
||||
void map_avx_beta(map_gen_t * s, int16_t * output[SRSLTE_TDEC_NPAR], uint32_t long_cb)
|
||||
void map_avx_beta(map_gen_t * s, int16_t * output[SRSLTE_TDEC_MAX_NPAR], uint32_t long_cb)
|
||||
{
|
||||
int k;
|
||||
uint32_t end = long_cb + 3;
|
||||
|
|
|
@ -54,13 +54,13 @@ void map_sse_alpha(map_gen_t * s, uint32_t long_cb);
|
|||
void map_sse_gamma(map_gen_t * h, int16_t *input, int16_t *app, int16_t *parity, uint32_t long_cb);
|
||||
|
||||
#ifdef LV_HAVE_AVX2
|
||||
void map_avx_beta(map_gen_t * s, int16_t * output[SRSLTE_TDEC_NPAR], uint32_t long_cb);
|
||||
void map_avx_beta(map_gen_t * s, int16_t * output[SRSLTE_TDEC_MAX_NPAR], uint32_t long_cb);
|
||||
void map_avx_alpha(map_gen_t * s, uint32_t long_cb);
|
||||
void map_avx_gamma(map_gen_t * h, int16_t *input, int16_t *app, int16_t *parity, uint32_t cbidx, uint32_t long_cb);
|
||||
#endif
|
||||
|
||||
|
||||
void map_simd_beta(map_gen_t * s, int16_t * output[SRSLTE_TDEC_NPAR], uint32_t nof_cb, uint32_t long_cb)
|
||||
void map_simd_beta(map_gen_t * s, int16_t * output[SRSLTE_TDEC_MAX_NPAR], uint32_t nof_cb, uint32_t long_cb)
|
||||
{
|
||||
if (nof_cb == 1) {
|
||||
map_sse_beta(s, output[0], long_cb);
|
||||
|
@ -128,12 +128,12 @@ void map_simd_free(map_gen_t * h)
|
|||
}
|
||||
|
||||
/* Runs one instance of a decoder */
|
||||
void map_simd_dec(map_gen_t * h, int16_t * input[SRSLTE_TDEC_NPAR], int16_t *app[SRSLTE_TDEC_NPAR], int16_t * parity[SRSLTE_TDEC_NPAR],
|
||||
int16_t *output[SRSLTE_TDEC_NPAR], uint32_t cb_mask, uint32_t long_cb)
|
||||
void map_simd_dec(map_gen_t * h, int16_t * input[SRSLTE_TDEC_MAX_NPAR], int16_t *app[SRSLTE_TDEC_MAX_NPAR], int16_t * parity[SRSLTE_TDEC_MAX_NPAR],
|
||||
int16_t *output[SRSLTE_TDEC_MAX_NPAR], uint32_t cb_mask, uint32_t long_cb)
|
||||
{
|
||||
|
||||
uint32_t nof_cb = 1;
|
||||
int16_t *outptr[SRSLTE_TDEC_NPAR];
|
||||
int16_t *outptr[SRSLTE_TDEC_MAX_NPAR];
|
||||
|
||||
// Compute branch metrics
|
||||
switch(cb_mask) {
|
||||
|
@ -354,21 +354,21 @@ void deinterleave_input_simd(srslte_tdec_simd_t *h, int16_t *input, uint32_t cbi
|
|||
}
|
||||
|
||||
/* Runs 1 turbo decoder iteration */
|
||||
void srslte_tdec_simd_iteration(srslte_tdec_simd_t * h, int16_t * input[SRSLTE_TDEC_NPAR], uint32_t long_cb)
|
||||
void srslte_tdec_simd_iteration(srslte_tdec_simd_t * h, int16_t * input[SRSLTE_TDEC_MAX_NPAR], uint32_t long_cb)
|
||||
{
|
||||
|
||||
int16_t *tmp_app[SRSLTE_TDEC_NPAR];
|
||||
int16_t *tmp_app[SRSLTE_TDEC_MAX_NPAR];
|
||||
|
||||
if (h->current_cbidx >= 0) {
|
||||
uint16_t *inter = h->interleaver[h->current_cbidx].forward;
|
||||
uint16_t *deinter = h->interleaver[h->current_cbidx].reverse;
|
||||
|
||||
#if SRSLTE_TDEC_NPAR == 2
|
||||
h->cb_mask = (input[0]?1:0) | (input[1]?2:0);
|
||||
#else
|
||||
h->cb_mask = input[0]?1:0;
|
||||
#ifndef LV_HAVE_AVX2
|
||||
input[1] = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
h->cb_mask = (input[0]?1:0) | (input[1]?2:0);
|
||||
|
||||
for (int i=0;i<h->max_par_cb;i++) {
|
||||
if (h->n_iter[i] == 0 && input[i]) {
|
||||
//printf("deinterleaveing %d\n",i);
|
||||
|
@ -484,7 +484,7 @@ void tdec_simd_decision(srslte_tdec_simd_t * h, uint8_t *output, uint32_t cbidx,
|
|||
}
|
||||
}
|
||||
|
||||
void srslte_tdec_simd_decision(srslte_tdec_simd_t * h, uint8_t *output[SRSLTE_TDEC_NPAR], uint32_t long_cb)
|
||||
void srslte_tdec_simd_decision(srslte_tdec_simd_t * h, uint8_t *output[SRSLTE_TDEC_MAX_NPAR], uint32_t long_cb)
|
||||
{
|
||||
for (int i=0;i<h->max_par_cb;i++) {
|
||||
tdec_simd_decision(h, output[i], i, long_cb);
|
||||
|
@ -510,7 +510,7 @@ void srslte_tdec_simd_decision_byte_cb(srslte_tdec_simd_t * h, uint8_t *output,
|
|||
}
|
||||
}
|
||||
|
||||
void srslte_tdec_simd_decision_byte(srslte_tdec_simd_t * h, uint8_t *output[SRSLTE_TDEC_NPAR], uint32_t long_cb)
|
||||
void srslte_tdec_simd_decision_byte(srslte_tdec_simd_t * h, uint8_t *output[SRSLTE_TDEC_MAX_NPAR], uint32_t long_cb)
|
||||
{
|
||||
for (int i=0;i<h->max_par_cb;i++) {
|
||||
srslte_tdec_simd_decision_byte_cb(h, output[i], i, long_cb);
|
||||
|
@ -519,7 +519,7 @@ void srslte_tdec_simd_decision_byte(srslte_tdec_simd_t * h, uint8_t *output[SRSL
|
|||
|
||||
|
||||
/* Runs nof_iterations iterations and decides the output bits */
|
||||
int srslte_tdec_simd_run_all(srslte_tdec_simd_t * h, int16_t * input[SRSLTE_TDEC_NPAR], uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
int srslte_tdec_simd_run_all(srslte_tdec_simd_t * h, int16_t * input[SRSLTE_TDEC_MAX_NPAR], uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_iterations, uint32_t long_cb)
|
||||
{
|
||||
if (srslte_tdec_simd_reset(h, long_cb)) {
|
||||
|
|
|
@ -172,7 +172,7 @@ void extract_input(srslte_tdec_simd_inter_t *h, int16_t *input, uint32_t cbidx,
|
|||
}
|
||||
}
|
||||
|
||||
void srslte_tdec_simd_inter_iteration(srslte_tdec_simd_inter_t * h, int16_t *input[SRSLTE_TDEC_NPAR], uint32_t nof_cb, uint32_t long_cb)
|
||||
void srslte_tdec_simd_inter_iteration(srslte_tdec_simd_inter_t * h, int16_t *input[SRSLTE_TDEC_MAX_NPAR], uint32_t nof_cb, uint32_t long_cb)
|
||||
{
|
||||
|
||||
if (h->current_cbidx >= 0) {
|
||||
|
@ -239,7 +239,7 @@ void srslte_tdec_simd_inter_decision_cb(srslte_tdec_simd_inter_t * h, uint8_t *o
|
|||
}
|
||||
}
|
||||
|
||||
void srslte_tdec_simd_inter_decision(srslte_tdec_simd_inter_t * h, uint8_t *output[SRSLTE_TDEC_NPAR], uint32_t nof_cb, uint32_t long_cb)
|
||||
void srslte_tdec_simd_inter_decision(srslte_tdec_simd_inter_t * h, uint8_t *output[SRSLTE_TDEC_MAX_NPAR], uint32_t nof_cb, uint32_t long_cb)
|
||||
{
|
||||
for (int i=0;i<nof_cb;i++) {
|
||||
srslte_tdec_simd_inter_decision_cb(h, output[i], i, long_cb);
|
||||
|
@ -269,7 +269,7 @@ void srslte_tdec_simd_inter_decision_byte_cb(srslte_tdec_simd_inter_t * h, uint8
|
|||
}
|
||||
}
|
||||
|
||||
void srslte_tdec_simd_inter_decision_byte(srslte_tdec_simd_inter_t * h, uint8_t *output[SRSLTE_TDEC_NPAR], uint32_t nof_cb, uint32_t long_cb)
|
||||
void srslte_tdec_simd_inter_decision_byte(srslte_tdec_simd_inter_t * h, uint8_t *output[SRSLTE_TDEC_MAX_NPAR], uint32_t nof_cb, uint32_t long_cb)
|
||||
{
|
||||
for (int i=0;i<nof_cb;i++) {
|
||||
srslte_tdec_simd_inter_decision_byte_cb(h, output[i], i, long_cb);
|
||||
|
@ -277,7 +277,7 @@ void srslte_tdec_simd_inter_decision_byte(srslte_tdec_simd_inter_t * h, uint8_t
|
|||
}
|
||||
|
||||
int srslte_tdec_simd_inter_run_all(srslte_tdec_simd_inter_t * h,
|
||||
int16_t *input[SRSLTE_TDEC_NPAR], uint8_t *output[SRSLTE_TDEC_NPAR],
|
||||
int16_t *input[SRSLTE_TDEC_MAX_NPAR], uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
|
||||
uint32_t nof_iterations, uint32_t nof_cb, uint32_t long_cb)
|
||||
{
|
||||
uint32_t iter = 0;
|
||||
|
|
|
@ -36,16 +36,15 @@
|
|||
|
||||
#ifdef LV_HAVE_SSE
|
||||
#include <immintrin.h>
|
||||
#include "srslte/phy/utils/mat.h"
|
||||
int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate);
|
||||
int srslte_predecoding_diversity2_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_symbols);
|
||||
#endif
|
||||
|
||||
#ifdef LV_HAVE_AVX
|
||||
#include <immintrin.h>
|
||||
#include "srslte/phy/utils/mat.h"
|
||||
int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate);
|
||||
#endif
|
||||
#include "srslte/phy/utils/mat.h"
|
||||
|
||||
|
||||
static srslte_mimo_decoder_t mimo_decoder = SRSLTE_MIMO_DECODER_MMSE;
|
||||
|
@ -1368,7 +1367,7 @@ int srslte_predecoding_multiplex(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_P
|
|||
int nof_rxant, int nof_ports, int nof_layers, int codebook_idx, int nof_symbols,
|
||||
float noise_estimate)
|
||||
{
|
||||
if (nof_ports == 2 && nof_rxant == 2) {
|
||||
if (nof_ports == 2 && nof_rxant <= 2) {
|
||||
if (nof_layers == 2) {
|
||||
switch (mimo_decoder) {
|
||||
case SRSLTE_MIMO_DECODER_ZF:
|
||||
|
@ -1408,7 +1407,7 @@ int srslte_predecoding_multiplex(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_P
|
|||
} else if (nof_ports == 4) {
|
||||
ERROR("Error predecoding multiplex: not implemented for %d Tx ports", nof_ports);
|
||||
} else {
|
||||
ERROR("Error predecoding multiplex: Invalid combination of ports %d and rx antennax %d\n", nof_ports, nof_rxant);
|
||||
ERROR("Error predecoding multiplex: Invalid combination of ports %d and rx antennas %d\n", nof_ports, nof_rxant);
|
||||
}
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <srslte/srslte.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
|
||||
#include "prb_dl.h"
|
||||
#include "srslte/phy/phch/pbch.h"
|
||||
|
@ -43,7 +45,6 @@
|
|||
#define PBCH_RE_CP_NORM 240
|
||||
#define PBCH_RE_CP_EXT 216
|
||||
|
||||
|
||||
const uint8_t srslte_crc_mask[4][16] = {
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
|
@ -139,33 +140,18 @@ int srslte_pbch_get(cf_t *slot1_data, cf_t *pbch, srslte_cell_t cell) {
|
|||
* At the receiver, the field nof_ports in the cell structure indicates the
|
||||
* maximum number of BS transmitter ports to look for.
|
||||
*/
|
||||
int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
|
||||
int srslte_pbch_init(srslte_pbch_t *q) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
bzero(q, sizeof(srslte_pbch_t));
|
||||
|
||||
if (cell.nof_ports == 0) {
|
||||
q->search_all_ports = true;
|
||||
cell.nof_ports = SRSLTE_MAX_PORTS;
|
||||
} else {
|
||||
q->search_all_ports = false;
|
||||
}
|
||||
|
||||
q->cell = cell;
|
||||
q->nof_symbols = (SRSLTE_CP_ISNORM(q->cell.cp)) ? PBCH_RE_CP_NORM : PBCH_RE_CP_EXT;
|
||||
|
||||
|
||||
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
|
||||
goto clean;
|
||||
}
|
||||
if (srslte_sequence_pbch(&q->seq, q->cell.cp, q->cell.id)) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
int poly[3] = { 0x6D, 0x4F, 0x57 };
|
||||
if (srslte_viterbi_init(&q->decoder, SRSLTE_VITERBI_37, poly, 40, true)) {
|
||||
goto clean;
|
||||
|
@ -178,12 +164,14 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
|
|||
q->encoder.tail_biting = true;
|
||||
memcpy(q->encoder.poly, poly, 3 * sizeof(int));
|
||||
|
||||
q->nof_symbols = PBCH_RE_CP_NORM;
|
||||
|
||||
q->d = srslte_vec_malloc(sizeof(cf_t) * q->nof_symbols);
|
||||
if (!q->d) {
|
||||
goto clean;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
q->ce[i] = srslte_vec_malloc(sizeof(cf_t) * q->nof_symbols);
|
||||
if (!q->ce[i]) {
|
||||
goto clean;
|
||||
|
@ -209,6 +197,7 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
|
|||
if (!q->rm_b) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
clean:
|
||||
|
@ -219,11 +208,11 @@ clean:
|
|||
}
|
||||
|
||||
void srslte_pbch_free(srslte_pbch_t *q) {
|
||||
if (q->d) {
|
||||
free(q->d);
|
||||
}
|
||||
srslte_sequence_free(&q->seq);
|
||||
srslte_modem_table_free(&q->mod);
|
||||
srslte_viterbi_free(&q->decoder);
|
||||
int i;
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
if (q->ce[i]) {
|
||||
free(q->ce[i]);
|
||||
}
|
||||
|
@ -243,12 +232,36 @@ void srslte_pbch_free(srslte_pbch_t *q) {
|
|||
if (q->rm_b) {
|
||||
free(q->rm_b);
|
||||
}
|
||||
srslte_sequence_free(&q->seq);
|
||||
srslte_modem_table_free(&q->mod);
|
||||
srslte_viterbi_free(&q->decoder);
|
||||
|
||||
if (q->d) {
|
||||
free(q->d);
|
||||
}
|
||||
bzero(q, sizeof(srslte_pbch_t));
|
||||
}
|
||||
|
||||
int srslte_pbch_set_cell(srslte_pbch_t *q, srslte_cell_t cell) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
if (cell.nof_ports == 0) {
|
||||
q->search_all_ports = true;
|
||||
cell.nof_ports = SRSLTE_MAX_PORTS;
|
||||
} else {
|
||||
q->search_all_ports = false;
|
||||
}
|
||||
|
||||
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
if (srslte_sequence_pbch(&q->seq, q->cell.cp, q->cell.id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
q->nof_symbols = (SRSLTE_CP_ISNORM(q->cell.cp)) ? PBCH_RE_CP_NORM : PBCH_RE_CP_EXT;
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -476,6 +489,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
|
|||
} else {
|
||||
nant = q->cell.nof_ports;
|
||||
}
|
||||
|
||||
do {
|
||||
if (nant != 3) {
|
||||
DEBUG("Trying %d TX antennas with %d frames\n", nant, q->frame_idx);
|
||||
|
@ -486,7 +500,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
|
|||
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, noise_estimate);
|
||||
} else {
|
||||
srslte_predecoding_diversity(q->symbols[0], q->ce, x, nant,
|
||||
q->nof_symbols);
|
||||
q->nof_symbols);
|
||||
srslte_layerdemap_diversity(x, q->d, nant, q->nof_symbols / nant);
|
||||
}
|
||||
|
||||
|
@ -577,7 +591,7 @@ int srslte_pbch_encode(srslte_pbch_t *q, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_
|
|||
if (q->cell.nof_ports > 1) {
|
||||
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols);
|
||||
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports,
|
||||
q->nof_symbols / q->cell.nof_ports);
|
||||
q->nof_symbols / q->cell.nof_ports);
|
||||
} else {
|
||||
memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t));
|
||||
}
|
||||
|
|
|
@ -57,38 +57,24 @@ bool srslte_pcfich_exists(int nframe, int nslot) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int srslte_pcfich_init(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
|
||||
return srslte_pcfich_init_multi(q, regs, cell, 1);
|
||||
}
|
||||
|
||||
/** Initializes the pcfich channel receiver.
|
||||
* On error, returns -1 and frees the structrure
|
||||
*/
|
||||
int srslte_pcfich_init_multi(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
|
||||
int srslte_pcfich_init(srslte_pcfich_t *q, uint32_t nof_rx_antennas) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
regs != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
bzero(q, sizeof(srslte_pcfich_t));
|
||||
q->cell = cell;
|
||||
q->regs = regs;
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
q->nof_symbols = PCFICH_RE;
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
|
||||
|
||||
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
|
||||
if (srslte_sequence_pcfich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert cfi bit tables to floats for demodulation */
|
||||
for (int i=0;i<3;i++) {
|
||||
for (int j=0;j<PCFICH_CFI_LEN;j++) {
|
||||
|
@ -115,6 +101,28 @@ void srslte_pcfich_free(srslte_pcfich_t *q) {
|
|||
bzero(q, sizeof(srslte_pcfich_t));
|
||||
}
|
||||
|
||||
int srslte_pcfich_set_cell(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
regs != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
q->regs = regs;
|
||||
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
|
||||
if (srslte_sequence_pcfich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** Finds the CFI with minimum distance with the vector of received 32 bits.
|
||||
* Saves the CFI value in the cfi pointer and returns the distance.
|
||||
*/
|
||||
|
@ -197,7 +205,7 @@ int srslte_pcfich_decode_multi(srslte_pcfich_t *q, cf_t *sf_symbols[SRSLTE_MAX_P
|
|||
}
|
||||
|
||||
q_symbols[j] = q->symbols[j];
|
||||
|
||||
|
||||
/* extract channel estimates */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (q->nof_symbols != srslte_regs_pcfich_get(q->regs, ce[i][j], q->ce[i][j])) {
|
||||
|
|
|
@ -61,41 +61,20 @@ float srslte_pdcch_coderate(uint32_t nof_bits, uint32_t l) {
|
|||
}
|
||||
|
||||
/** Initializes the PDCCH transmitter and receiver */
|
||||
int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
|
||||
return srslte_pdcch_init_multi(q, regs, cell, 1);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_tx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
|
||||
return srslte_pdcch_init_txrx(q, regs, cell, 1, false);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_rx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
|
||||
return srslte_pdcch_init_txrx(q, regs, cell, nof_rx_antennas, true);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
|
||||
return srslte_pdcch_init_txrx(q, regs, cell, nof_rx_antennas, true);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas, bool isReceiver)
|
||||
static int pdcch_init(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas, bool is_ue)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
regs != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
ret = SRSLTE_ERROR;
|
||||
bzero(q, sizeof(srslte_pdcch_t));
|
||||
q->cell = cell;
|
||||
q->regs = regs;
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
q->is_ue = is_ue;
|
||||
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
|
||||
q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72;
|
||||
q->max_bits = max_prb*3*12*2;
|
||||
|
||||
INFO("Init PDCCH: Max bits: %d, %d ports.\n",
|
||||
q->max_bits, q->cell.nof_ports);
|
||||
INFO("Init PDCCH: Max bits: %d\n", q->max_bits);
|
||||
|
||||
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
|
||||
goto clean;
|
||||
|
@ -104,14 +83,6 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
|
|||
goto clean;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
// we need to pregenerate the sequence for the maximum number of bits, which is 8 times
|
||||
// the maximum number of REGs (for CFI=3)
|
||||
if (srslte_sequence_pdcch(&q->seq[i], 2 * i, q->cell.id, 8*srslte_regs_pdcch_nregs(q->regs, 3))) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
int poly[3] = { 0x6D, 0x4F, 0x57 };
|
||||
if (srslte_viterbi_init(&q->decoder, SRSLTE_VITERBI_37, poly, SRSLTE_DCI_MAX_BITS + 16, true)) {
|
||||
goto clean;
|
||||
|
@ -134,8 +105,16 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
|
|||
goto clean;
|
||||
}
|
||||
|
||||
if (isReceiver) {
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->x[i]) {
|
||||
goto clean;
|
||||
}
|
||||
q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->symbols[i]) {
|
||||
goto clean;
|
||||
}
|
||||
if (q->is_ue) {
|
||||
for (int j = 0; j < q->nof_rx_antennas; j++) {
|
||||
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->ce[i][j]) {
|
||||
|
@ -145,20 +124,6 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->x[i]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < ((isReceiver) ? q->nof_rx_antennas : cell.nof_ports); j++) {
|
||||
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->symbols[j]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
clean:
|
||||
|
@ -168,6 +133,14 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
|
|||
return ret;
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_enb(srslte_pdcch_t *q, uint32_t max_prb) {
|
||||
return pdcch_init(q, max_prb, 0, false);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_ue(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas) {
|
||||
return pdcch_init(q, max_prb, nof_rx_antennas, true);
|
||||
}
|
||||
|
||||
void srslte_pdcch_free(srslte_pdcch_t *q) {
|
||||
|
||||
if (q->e) {
|
||||
|
@ -180,18 +153,18 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
|
|||
free(q->d);
|
||||
}
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
if (q->ce[i][j]) {
|
||||
free(q->ce[i][j]);
|
||||
}
|
||||
}
|
||||
if (q->x[i]) {
|
||||
free(q->x[i]);
|
||||
}
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
if (q->symbols[j]) {
|
||||
free(q->symbols[j]);
|
||||
if (q->symbols[i]) {
|
||||
free(q->symbols[i]);
|
||||
}
|
||||
if (q->is_ue) {
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
if (q->ce[i][j]) {
|
||||
free(q->ce[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
|
@ -205,6 +178,39 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
|
|||
|
||||
}
|
||||
|
||||
int srslte_pdcch_set_cell(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
regs != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
q->regs = regs;
|
||||
|
||||
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
|
||||
q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72;
|
||||
|
||||
INFO("PDCCH: Cell config PCI=%d, %d ports.\n",
|
||||
q->cell.id, q->cell.nof_ports);
|
||||
|
||||
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
// we need to pregenerate the sequence for the maximum number of bits, which is 8 times
|
||||
// the maximum number of REGs (for CFI=3)
|
||||
if (srslte_sequence_pdcch(&q->seq[i], 2 * i, q->cell.id, 8*srslte_regs_pdcch_nregs(q->regs, 3))) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, uint32_t max_candidates,
|
||||
uint32_t nsubframe, uint32_t cfi, uint16_t rnti)
|
||||
{
|
||||
|
@ -490,7 +496,7 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA
|
|||
|
||||
/* descramble */
|
||||
srslte_scrambling_f_offset(&q->seq[nsubframe], q->llr, 0, e_bits);
|
||||
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
|
|
|
@ -27,17 +27,11 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "prb_dl.h"
|
||||
#include "srslte/phy/phch/pdsch.h"
|
||||
#include "srslte/phy/phch/sch.h"
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
#include "srslte/phy/utils/bit.h"
|
||||
#include "srslte/phy/utils/debug.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
||||
|
@ -45,7 +39,6 @@
|
|||
#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
|
||||
|
||||
|
||||
|
||||
const static srslte_mod_t modulations[4] =
|
||||
{ SRSLTE_MOD_BPSK, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, SRSLTE_MOD_64QAM };
|
||||
|
||||
|
@ -197,30 +190,24 @@ int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols,
|
|||
return srslte_pdsch_cp(q, sf_symbols, symbols, grant, lstart, subframe, false);
|
||||
}
|
||||
|
||||
/** Initializes the PDCCH transmitter or receiver */
|
||||
int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antennas, bool is_receiver)
|
||||
/** Initializes the PDSCH transmitter and receiver */
|
||||
static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t nof_antennas)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
int i;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell) &&
|
||||
nof_antennas <= SRSLTE_MAX_PORTS)
|
||||
{
|
||||
if (q != NULL)
|
||||
{
|
||||
|
||||
bzero(q, sizeof(srslte_pdsch_t));
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
q->cell = cell;
|
||||
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
|
||||
if (is_receiver) {
|
||||
q->nof_rx_antennas = nof_antennas;
|
||||
}
|
||||
q->max_re = max_prb * MAX_PDSCH_RE(q->cell.cp);
|
||||
q->is_ue = is_ue;
|
||||
q->nof_rx_antennas = nof_antennas;
|
||||
|
||||
INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
|
||||
q->cell.nof_prb, q->max_re);
|
||||
INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
|
||||
goto clean;
|
||||
}
|
||||
|
@ -232,7 +219,7 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
|
|||
goto clean;
|
||||
}
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
// Allocate int16_t for reception (LLRs)
|
||||
q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
|
||||
if (!q->e[i]) {
|
||||
|
@ -245,18 +232,17 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
|
|||
}
|
||||
}
|
||||
|
||||
/* Layer mapped symbols memory allocation */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->x[i]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it is the receiver side, allocate estimated channel */
|
||||
if (is_receiver) {
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
for (int j = 0; j < q->nof_rx_antennas; j++) {
|
||||
q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->symbols[i]) {
|
||||
goto clean;
|
||||
}
|
||||
if (q->is_ue) {
|
||||
for (int j = 0; j < SRSLTE_MAX_PORTS; j++) {
|
||||
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->ce[i][j]) {
|
||||
goto clean;
|
||||
|
@ -264,42 +250,40 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
|
|||
}
|
||||
}
|
||||
}
|
||||
for (int j=0;j<SRSLTE_MAX(q->nof_rx_antennas, q->cell.nof_ports);j++) {
|
||||
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->symbols[j]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate User memory (all zeros) */
|
||||
q->users = calloc(sizeof(srslte_pdsch_user_t*), 1+SRSLTE_SIRNTI);
|
||||
|
||||
q->users = calloc(sizeof(srslte_pdsch_user_t*), q->is_ue?1:(1+SRSLTE_SIRNTI));
|
||||
if (!q->users) {
|
||||
perror("malloc");
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
clean:
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
clean:
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
srslte_pdsch_free(q);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srslte_pdsch_init_tx(srslte_pdsch_t *q, srslte_cell_t cell) {
|
||||
return srslte_pdsch_init(q, cell, 0, false);
|
||||
int srslte_pdsch_init_ue(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_antennas)
|
||||
{
|
||||
return pdsch_init(q, max_prb, true, nof_antennas);
|
||||
}
|
||||
|
||||
int srslte_pdsch_init_rx(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antennas) {
|
||||
return srslte_pdsch_init(q, cell, nof_antennas, true);
|
||||
int srslte_pdsch_init_enb(srslte_pdsch_t *q, uint32_t max_prb)
|
||||
{
|
||||
return pdsch_init(q, max_prb, false, 0);
|
||||
}
|
||||
|
||||
void srslte_pdsch_free(srslte_pdsch_t *q) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
|
||||
if (q->e[i]) {
|
||||
free(q->e[i]);
|
||||
|
@ -313,69 +297,107 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
|
|||
/* Free sch objects */
|
||||
srslte_sch_free(&q->dl_sch);
|
||||
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
if (q->x[i]) {
|
||||
free(q->x[i]);
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
if (q->ce[i][j]) {
|
||||
free(q->ce[i][j]);
|
||||
if (q->symbols[i]) {
|
||||
free(q->symbols[i]);
|
||||
}
|
||||
if (q->is_ue) {
|
||||
for (int j = 0; j < SRSLTE_MAX_PORTS; j++) {
|
||||
if (q->ce[i][j]) {
|
||||
free(q->ce[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j=0;j<SRSLTE_MAX_PORTS;j++) {
|
||||
if (q->symbols[j]) {
|
||||
free(q->symbols[j]);
|
||||
}
|
||||
}
|
||||
if (q->users) {
|
||||
for (uint16_t u=0;u<SRSLTE_SIRNTI;u++) {
|
||||
if (q->users[u]) {
|
||||
srslte_pdsch_free_rnti(q, u);
|
||||
if (q->is_ue) {
|
||||
srslte_pdsch_free_rnti(q, 0);
|
||||
} else {
|
||||
for (int u=0;u<=SRSLTE_SIRNTI;u++) {
|
||||
if (q->users[u]) {
|
||||
srslte_pdsch_free_rnti(q, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(q->users);
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
||||
srslte_sequence_free(&q->tmp_seq);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
srslte_modem_table_free(&q->mod[i]);
|
||||
}
|
||||
|
||||
bzero(q, sizeof(srslte_pdsch_t));
|
||||
}
|
||||
|
||||
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
|
||||
int srslte_pdsch_set_cell(srslte_pdsch_t *q, srslte_cell_t cell)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
|
||||
|
||||
INFO("PDSCH: Cell config PCI=%d, %d ports, %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
|
||||
q->cell.id, q->cell.nof_prb, q->max_re);
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
|
||||
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
|
||||
*/
|
||||
int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
|
||||
uint32_t i, j;
|
||||
if (!q->users[rnti]) {
|
||||
q->users[rnti] = calloc(1, sizeof(srslte_pdsch_user_t));
|
||||
if (q->users[rnti]) {
|
||||
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
for (j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
|
||||
if (srslte_sequence_pdsch(&q->users[rnti]->seq[j][i], rnti, j, 2 * i, q->cell.id,
|
||||
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
|
||||
ERROR("Generating scrambling sequence");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
uint32_t rnti_idx = q->is_ue?0:rnti;
|
||||
|
||||
if (!q->users[rnti_idx] || q->is_ue) {
|
||||
if (!q->users[rnti_idx]) {
|
||||
q->users[rnti_idx] = calloc(1, sizeof(srslte_pdsch_user_t));
|
||||
if(!q->users[rnti_idx]) {
|
||||
perror("calloc");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
|
||||
if (srslte_sequence_pdsch(&q->users[rnti_idx]->seq[j][i], rnti, j, 2 * i, q->cell.id,
|
||||
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)))
|
||||
{
|
||||
fprintf(stderr, "Error initializing PDSCH scrambling sequence\n");
|
||||
srslte_pdsch_free_rnti(q, rnti);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
q->users[rnti]->sequence_generated = true;
|
||||
}
|
||||
q->ue_rnti = rnti;
|
||||
q->users[rnti_idx]->cell_id = q->cell.id;
|
||||
q->users[rnti_idx]->sequence_generated = true;
|
||||
} else {
|
||||
fprintf(stderr, "Error generating PDSCH sequence: rnti=0x%x already generated\n", rnti);
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti)
|
||||
{
|
||||
if (q->users[rnti]) {
|
||||
uint32_t rnti_idx = q->is_ue?0:rnti;
|
||||
if (q->users[rnti_idx]) {
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
|
||||
srslte_sequence_free(&q->users[rnti]->seq[j][i]);
|
||||
srslte_sequence_free(&q->users[rnti_idx]->seq[j][i]);
|
||||
}
|
||||
}
|
||||
free(q->users[rnti]);
|
||||
q->users[rnti] = NULL;
|
||||
free(q->users[rnti_idx]);
|
||||
q->users[rnti_idx] = NULL;
|
||||
q->ue_rnti = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,7 +412,7 @@ static void pdsch_decode_debug(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
|
|||
break;
|
||||
}
|
||||
DEBUG("SAVED FILE %s: received subframe symbols\n", filename);
|
||||
srslte_vec_save_file(filename, sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
srslte_vec_save_file(filename, sf_symbols[j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
|
||||
for (int i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (snprintf(filename, FILENAME_MAX, "hest_%d%d.dat", i, j) < 0) {
|
||||
|
@ -401,11 +423,21 @@ static void pdsch_decode_debug(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
|
|||
srslte_vec_save_file(filename, ce[i][j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
}
|
||||
}
|
||||
DEBUG("SAVED FILE pdsch_symbols.dat: symbols after equalization\n",0);
|
||||
srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits[0].nof_re*sizeof(cf_t));
|
||||
for (int i=0;i<cfg->nof_layers;i++) {
|
||||
if (snprintf(filename, FILENAME_MAX, "pdsch_symbols_%d.dat", i) < 0) {
|
||||
ERROR("Generating file name");
|
||||
break;
|
||||
}
|
||||
DEBUG("SAVED FILE %s: symbols after equalization\n", filename);
|
||||
srslte_vec_save_file(filename, q->d[i], cfg->nbits[0].nof_re*sizeof(cf_t));
|
||||
|
||||
DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0);
|
||||
srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t));
|
||||
if (snprintf(filename, FILENAME_MAX, "llr_%d.dat", i) < 0) {
|
||||
ERROR("Generating file name");
|
||||
break;
|
||||
}
|
||||
DEBUG("SAVED FILE %s: LLR estimates after demodulation and descrambling\n", filename);
|
||||
srslte_vec_save_file(filename, q->e[i], cfg->nbits[0].nof_bits*sizeof(int16_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,15 +459,17 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_g
|
|||
int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi,
|
||||
uint32_t sf_idx, int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type,
|
||||
uint32_t pmi) {
|
||||
if (cfg) {
|
||||
if (grant) {
|
||||
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
|
||||
}
|
||||
if (cfg && grant) {
|
||||
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
|
||||
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
|
||||
|
||||
for (int i = 0; i < grant->nof_tb; i++) {
|
||||
if (srslte_cbsegm(&cfg->cb_segm[i], (uint32_t) cfg->grant.mcs[i].tbs)) {
|
||||
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[i].tbs);
|
||||
return SRSLTE_ERROR;
|
||||
|
||||
for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) {
|
||||
if (grant->tb_en[cw]) {
|
||||
if (srslte_cbsegm(&cfg->cb_segm[cw], (uint32_t) cfg->grant.mcs[cw].tbs)) {
|
||||
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[cw].tbs);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits);
|
||||
|
@ -447,33 +481,36 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra
|
|||
/* Check and configure PDSCH transmission modes */
|
||||
switch(mimo_type) {
|
||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||
if (grant->nof_tb != 1) {
|
||||
ERROR("Number of transport blocks is not supported for single transmission mode.");
|
||||
if (nof_tb != 1) {
|
||||
ERROR("Wrong number of transport blocks (%d) for single antenna.", nof_tb);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
cfg->nof_layers = 1;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
if (grant->nof_tb != 1) {
|
||||
ERROR("Number of transport blocks is not supported for transmit diversity mode.");
|
||||
if (nof_tb != 1) {
|
||||
ERROR("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
cfg->nof_layers = 2;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
|
||||
if (grant->nof_tb == 1) {
|
||||
if (nof_tb == 1) {
|
||||
cfg->codebook_idx = pmi;
|
||||
cfg->nof_layers = 1;
|
||||
} else {
|
||||
} else if (nof_tb == 2) {
|
||||
cfg->codebook_idx = pmi + 1;
|
||||
cfg->nof_layers = 2;
|
||||
} else {
|
||||
ERROR("Wrong number of transport blocks (%d) for spatial multiplexing.", nof_tb);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
INFO("PDSCH configured for Spatial Multiplex; nof_codewords=%d; nof_layers=%d; codebook_idx=%d;\n",
|
||||
grant->nof_tb, cfg->nof_layers, cfg->codebook_idx);
|
||||
nof_tb, cfg->nof_layers, cfg->codebook_idx);
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_CDD:
|
||||
if (grant->nof_tb != 2) {
|
||||
ERROR("Number of transport blocks (%d) is not supported for CDD transmission mode.", grant->nof_tb);
|
||||
if (nof_tb != 2) {
|
||||
ERROR("Wrong number of transport blocks (%d) for CDD.", nof_tb);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
cfg->nof_layers = 2;
|
||||
|
@ -486,7 +523,25 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra
|
|||
}
|
||||
}
|
||||
|
||||
static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
|
||||
static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti,
|
||||
uint32_t codeword_idx, uint32_t sf_idx, uint32_t len)
|
||||
{
|
||||
uint32_t rnti_idx = q->is_ue?0:rnti;
|
||||
|
||||
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
|
||||
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated &&
|
||||
q->users[rnti_idx]->cell_id == q->cell.id &&
|
||||
q->ue_rnti == rnti &&
|
||||
((rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) || !q->is_ue))
|
||||
{
|
||||
return &q->users[rnti_idx]->seq[codeword_idx][sf_idx];
|
||||
} else {
|
||||
srslte_sequence_pdsch(&q->tmp_seq, rnti, codeword_idx, 2 * sf_idx, q->cell.id, len);
|
||||
return &q->tmp_seq;
|
||||
}
|
||||
}
|
||||
|
||||
static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data,
|
||||
uint32_t codeword_idx) {
|
||||
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
|
||||
|
@ -499,45 +554,36 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
|
|||
nbits->nof_re, nbits->nof_bits, rv);
|
||||
|
||||
/* Channel coding */
|
||||
if (srslte_dlsch_encode2(&pdsch->dl_sch, cfg, softbuffer, data, pdsch->e[codeword_idx], codeword_idx)) {
|
||||
if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], codeword_idx)) {
|
||||
ERROR("Error encoding TB %d", codeword_idx);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
/* Select scrambling sequence */
|
||||
srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits);
|
||||
|
||||
/* Bit scrambling */
|
||||
if (!pdsch->users[rnti]) {
|
||||
srslte_sequence_t seq;
|
||||
|
||||
if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) {
|
||||
ERROR("Initialising scrambling sequence");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_scrambling_bytes(&seq, (uint8_t *) pdsch->e[codeword_idx], nbits->nof_bits);
|
||||
srslte_sequence_free(&seq);
|
||||
|
||||
} else {
|
||||
srslte_scrambling_bytes(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx],
|
||||
(uint8_t *) pdsch->e[codeword_idx],
|
||||
nbits->nof_bits);
|
||||
}
|
||||
srslte_scrambling_bytes(seq, (uint8_t *) q->e[codeword_idx], nbits->nof_bits);
|
||||
|
||||
/* Bit mapping */
|
||||
srslte_mod_modulate_bytes(&pdsch->mod[mcs->mod],
|
||||
(uint8_t *) pdsch->e[codeword_idx],
|
||||
pdsch->d[codeword_idx], nbits->nof_bits);
|
||||
srslte_mod_modulate_bytes(&q->mod[mcs->mod],
|
||||
(uint8_t *) q->e[codeword_idx],
|
||||
q->d[codeword_idx], nbits->nof_bits);
|
||||
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
|
||||
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data,
|
||||
uint32_t codeword_idx) {
|
||||
uint32_t codeword_idx, bool *ack) {
|
||||
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
|
||||
srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx];
|
||||
uint32_t rv = cfg->rv[codeword_idx];
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (nbits->nof_bits) {
|
||||
if (softbuffer && data && ack) {
|
||||
INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
|
||||
cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
|
||||
nbits->nof_re, nbits->nof_bits, rv);
|
||||
|
@ -546,25 +592,30 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
|
|||
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
|
||||
* thus we don't need tot set it in the LLRs normalization
|
||||
*/
|
||||
srslte_demod_soft_demodulate_s(mcs->mod, pdsch->d[codeword_idx], pdsch->e[codeword_idx], nbits->nof_re);
|
||||
srslte_demod_soft_demodulate_s(mcs->mod, q->d[codeword_idx], q->e[codeword_idx], nbits->nof_re);
|
||||
|
||||
if (pdsch->users[rnti] && pdsch->users[rnti]->sequence_generated) {
|
||||
srslte_scrambling_s_offset(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx], pdsch->e[codeword_idx],
|
||||
0, nbits->nof_bits);
|
||||
} else {
|
||||
srslte_sequence_t seq;
|
||||
if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) {
|
||||
ERROR("Initialising scrambling sequence");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_scrambling_s_offset(&seq, pdsch->e[codeword_idx], 0, nbits->nof_bits);
|
||||
srslte_sequence_free(&seq);
|
||||
/* Select scrambling sequence */
|
||||
srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits);
|
||||
|
||||
/* Bit scrambling */
|
||||
srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits);
|
||||
|
||||
/* Return */
|
||||
ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, codeword_idx);
|
||||
|
||||
q->last_nof_iterations[codeword_idx] = srslte_sch_last_noi(&q->dl_sch);
|
||||
|
||||
if (ret == SRSLTE_SUCCESS) {
|
||||
*ack = true;
|
||||
} else if (ret == SRSLTE_ERROR) {
|
||||
*ack = false;
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
return srslte_dlsch_decode2(&pdsch->dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx);
|
||||
} else {
|
||||
ERROR("Detected NULL pointer in TB%d &softbuffer=%p &data=%p &ack=%p", codeword_idx, softbuffer, (void*)data, ack);
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Decodes the PDSCH from the received symbols
|
||||
|
@ -585,9 +636,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
|
|||
data != NULL &&
|
||||
cfg != NULL)
|
||||
{
|
||||
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant);
|
||||
|
||||
INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, NofSymbols: %d, C_prb=%d, mimo_type=%d, nof_layers=%d, nof_tb=%d\n",
|
||||
cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, cfg->nof_layers, cfg->grant.nof_tb);
|
||||
cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, cfg->nof_layers, nof_tb);
|
||||
|
||||
// Extract Symbols and Channel Estimates
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
|
@ -608,10 +660,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
|
|||
|
||||
// Prepare layers
|
||||
int nof_symbols [SRSLTE_MAX_CODEWORDS];
|
||||
nof_symbols[0] = cfg->nbits[0].nof_re * cfg->grant.nof_tb / cfg->nof_layers;
|
||||
nof_symbols[1] = cfg->nbits[1].nof_re * cfg->grant.nof_tb / cfg->nof_layers;
|
||||
nof_symbols[0] = cfg->nbits[0].nof_re * nof_tb / cfg->nof_layers;
|
||||
nof_symbols[1] = cfg->nbits[1].nof_re * nof_tb / cfg->nof_layers;
|
||||
|
||||
if (cfg->nof_layers == cfg->grant.nof_tb) {
|
||||
if (cfg->nof_layers == nof_tb) {
|
||||
/* Skip layer demap */
|
||||
for (i = 0; i < cfg->nof_layers; i++) {
|
||||
x[i] = q->d[i];
|
||||
|
@ -629,21 +681,26 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
|
|||
cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate);
|
||||
|
||||
// Layer demapping only if necessary
|
||||
if (cfg->nof_layers != cfg->grant.nof_tb) {
|
||||
srslte_layerdemap_type(x, q->d, cfg->nof_layers, cfg->grant.nof_tb,
|
||||
if (cfg->nof_layers != nof_tb) {
|
||||
srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb,
|
||||
nof_symbols[0], nof_symbols, cfg->mimo_type);
|
||||
}
|
||||
|
||||
// Codeword decoding
|
||||
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
|
||||
int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
|
||||
acks[tb] = (ret == SRSLTE_SUCCESS);
|
||||
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) {
|
||||
/* Decode only if transport block is enabled and the default ACK is not true */
|
||||
if (cfg->grant.tb_en[tb] && !acks[tb]) {
|
||||
int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]);
|
||||
|
||||
/* Check if there has been any execution error */
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdsch_decode_debug(q, cfg, sf_symbols, ce);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
@ -654,8 +711,9 @@ int srslte_pdsch_pmi_select(srslte_pdsch_t *q,
|
|||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, uint32_t nof_ce,
|
||||
uint32_t pmi[SRSLTE_MAX_LAYERS], float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS]) {
|
||||
|
||||
if (q->cell.nof_ports == 2 && q->nof_rx_antennas == 2) {
|
||||
for (int nof_layers = 1; nof_layers <= 2; nof_layers++ ) {
|
||||
if (q->cell.nof_ports == 2 && q->nof_rx_antennas <= 2) {
|
||||
int nof_layers = 1;
|
||||
for (; nof_layers <= q->nof_rx_antennas; nof_layers++ ) {
|
||||
if (sinr[nof_layers - 1] && pmi) {
|
||||
if (srslte_precoding_pmi_select(ce, nof_ce, noise_estimate, nof_layers, &pmi[nof_layers - 1],
|
||||
sinr[nof_layers - 1]) < 0) {
|
||||
|
@ -664,6 +722,16 @@ int srslte_pdsch_pmi_select(srslte_pdsch_t *q,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Set other layers to 0 */
|
||||
for (; nof_layers <= SRSLTE_MAX_LAYERS; nof_layers++ ) {
|
||||
if (sinr[nof_layers - 1] && pmi) {
|
||||
for (int cb = 0; cb < SRSLTE_MAX_CODEBOOKS; cb++) {
|
||||
sinr[nof_layers - 1][cb] = -INFINITY;
|
||||
}
|
||||
pmi[nof_layers - 1] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ERROR("Not implemented configuration");
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
@ -689,6 +757,8 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
|
|||
|
||||
if (q != NULL &&
|
||||
cfg != NULL) {
|
||||
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant);
|
||||
|
||||
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (sf_symbols[i] == NULL) {
|
||||
|
@ -708,15 +778,17 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
|
|||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
|
||||
ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
|
||||
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) {
|
||||
if (cfg->grant.tb_en[tb]) {
|
||||
ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
|
||||
}
|
||||
}
|
||||
|
||||
// Layer mapping & precode if necessary
|
||||
if (q->cell.nof_ports > 1) {
|
||||
int nof_symbols;
|
||||
/* If number of layers is equal to transport blocks (codewords) skip layer mapping */
|
||||
if (cfg->nof_layers == cfg->grant.nof_tb) {
|
||||
if (cfg->nof_layers == nof_tb) {
|
||||
for (i = 0; i < cfg->nof_layers; i++) {
|
||||
x[i] = q->d[i];
|
||||
}
|
||||
|
@ -728,7 +800,7 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
|
|||
}
|
||||
memset(&x[cfg->nof_layers], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - cfg->nof_layers));
|
||||
|
||||
nof_symbols = srslte_layermap_type(q->d, x, cfg->grant.nof_tb, cfg->nof_layers,
|
||||
nof_symbols = srslte_layermap_type(q->d, x, nof_tb, cfg->nof_layers,
|
||||
(int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits[0].nof_re, cfg->nbits[1].nof_re},
|
||||
cfg->mimo_type);
|
||||
}
|
||||
|
@ -754,14 +826,13 @@ void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, uint32_t max_iter) {
|
|||
srslte_sch_set_max_noi(&q->dl_sch, max_iter);
|
||||
}
|
||||
|
||||
float srslte_pdsch_average_noi(srslte_pdsch_t *q) {
|
||||
return q->dl_sch.average_nof_iterations;
|
||||
float srslte_pdsch_last_noi(srslte_pdsch_t *q) {
|
||||
return srslte_pdsch_last_noi_cw(q, 0);
|
||||
}
|
||||
|
||||
uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q) {
|
||||
return q->dl_sch.nof_iterations;
|
||||
uint32_t srslte_pdsch_last_noi_cw(srslte_pdsch_t *q, uint32_t cw_idx) {
|
||||
return q->last_nof_iterations[cw_idx];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
|
||||
#include "srslte/phy/phch/regs.h"
|
||||
#include "srslte/phy/phch/phich.h"
|
||||
|
@ -67,37 +68,22 @@ void srslte_phich_reset(srslte_phich_t *q, cf_t *slot_symbols[SRSLTE_MAX_PORTS])
|
|||
}
|
||||
}
|
||||
|
||||
int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell)
|
||||
{
|
||||
return srslte_phich_init_multi(q, regs, cell, 1);
|
||||
}
|
||||
|
||||
/** Initializes the phich channel receiver */
|
||||
int srslte_phich_init_multi(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas)
|
||||
int srslte_phich_init(srslte_phich_t *q, uint32_t nof_rx_antennas)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
regs != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
|
||||
bzero(q, sizeof(srslte_phich_t));
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
q->cell = cell;
|
||||
q->regs = regs;
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
|
||||
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK)) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
|
||||
if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
clean:
|
||||
|
@ -114,9 +100,34 @@ void srslte_phich_free(srslte_phich_t *q) {
|
|||
srslte_modem_table_free(&q->mod);
|
||||
|
||||
bzero(q, sizeof(srslte_phich_t));
|
||||
|
||||
}
|
||||
|
||||
int srslte_phich_set_cell(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
regs != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
{
|
||||
|
||||
q->regs = regs;
|
||||
|
||||
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
|
||||
if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Computes n_group and n_seq according to Section 9.1.2 in 36.213 */
|
||||
void srslte_phich_calc(srslte_phich_t *q, uint32_t n_prb_lowest, uint32_t n_dmrs,
|
||||
uint32_t *ngroup, uint32_t *nseq)
|
||||
|
@ -162,26 +173,9 @@ void srslte_phich_ack_encode(uint8_t ack, uint8_t bits[SRSLTE_PHICH_NBITS]) {
|
|||
memset(bits, ack, 3 * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
int srslte_phich_decode(srslte_phich_t *q, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate,
|
||||
uint32_t ngroup, uint32_t nseq, uint32_t subframe, uint8_t *ack, float *distance)
|
||||
{
|
||||
cf_t *_sf_symbols[SRSLTE_MAX_PORTS];
|
||||
cf_t *_ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
|
||||
_sf_symbols[0] = sf_symbols;
|
||||
for (int i=0;i<q->cell.nof_ports;i++) {
|
||||
_ce[i][0] = ce[i];
|
||||
}
|
||||
|
||||
return srslte_phich_decode_multi(q, _sf_symbols, _ce, noise_estimate, ngroup, nseq, subframe, ack, distance);
|
||||
}
|
||||
/* Decodes the phich channel and saves the CFI in the cfi pointer.
|
||||
*
|
||||
* Returns 1 if successfully decoded the CFI, 0 if not and -1 on error
|
||||
*/
|
||||
int srslte_phich_decode_multi(srslte_phich_t *q, cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate,
|
||||
uint32_t ngroup, uint32_t nseq, uint32_t subframe, uint8_t *ack, float *distance)
|
||||
{
|
||||
int srslte_phich_decode(srslte_phich_t *q, cf_t *sf_symbols[SRSLTE_MAX_PORTS],
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate,
|
||||
uint32_t ngroup, uint32_t nseq, uint32_t subframe, uint8_t *ack, float *distance) {
|
||||
|
||||
/* Set pointers for layermapping & precoding */
|
||||
int i, j;
|
||||
|
|
|
@ -0,0 +1,480 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2015 Software Radio Systems Limited
|
||||
*
|
||||
* \section LICENSE
|
||||
*
|
||||
* This file is part of the srsLTE library.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE 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 Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "prb_dl.h"
|
||||
#include "srslte/phy/phch/sch.h"
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
#include "srslte/phy/utils/bit.h"
|
||||
#include "srslte/phy/utils/debug.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
||||
|
||||
#define MAX_PMCH_RE (2 * SRSLTE_CP_EXT_NSYMB * 12)
|
||||
|
||||
|
||||
const static srslte_mod_t modulations[4] =
|
||||
{ SRSLTE_MOD_BPSK, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, SRSLTE_MOD_64QAM };
|
||||
|
||||
//#define DEBUG_IDX
|
||||
|
||||
#ifdef DEBUG_IDX
|
||||
cf_t *offset_original=NULL;
|
||||
extern int indices[100000];
|
||||
extern int indices_ptr;
|
||||
#endif
|
||||
|
||||
float srslte_pmch_coderate(uint32_t tbs, uint32_t nof_re)
|
||||
{
|
||||
return (float) (tbs + 24)/(nof_re);
|
||||
}
|
||||
|
||||
int srslte_pmch_cp(srslte_pmch_t *q, cf_t *input, cf_t *output, uint32_t lstart_grant, bool put)
|
||||
{
|
||||
uint32_t s, n, l, lp, lstart, lend, nof_refs;
|
||||
cf_t *in_ptr = input, *out_ptr = output;
|
||||
uint32_t offset = 0;
|
||||
|
||||
#ifdef DEBUG_IDX
|
||||
indices_ptr = 0;
|
||||
if (put) {
|
||||
offset_original = output;
|
||||
} else {
|
||||
offset_original = input;
|
||||
}
|
||||
#endif
|
||||
nof_refs = 6;
|
||||
for (s = 0; s < 2; s++) {
|
||||
for (l = 0; l < SRSLTE_CP_EXT_NSYMB; l++) {
|
||||
for (n = 0; n < q->cell.nof_prb; n++) {
|
||||
// If this PRB is assigned
|
||||
if (true) {
|
||||
if (s == 0) {
|
||||
lstart = lstart_grant;
|
||||
} else {
|
||||
lstart = 0;
|
||||
}
|
||||
lend = SRSLTE_CP_EXT_NSYMB;
|
||||
lp = l + s * SRSLTE_CP_EXT_NSYMB;
|
||||
if (put) {
|
||||
out_ptr = &output[(lp * q->cell.nof_prb + n) * SRSLTE_NRE];
|
||||
} else {
|
||||
in_ptr = &input[(lp * q->cell.nof_prb + n) * SRSLTE_NRE];
|
||||
}
|
||||
// This is a symbol in a normal PRB with or without references
|
||||
if (l >= lstart && l < lend) {
|
||||
if (SRSLTE_SYMBOL_HAS_REF_MBSFN(l,s)) {
|
||||
if (l == 0 && s == 1) {
|
||||
offset = 1;
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs, put);
|
||||
} else {
|
||||
prb_cp(&in_ptr, &out_ptr, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int r;
|
||||
if (put) {
|
||||
r = abs((int) (input - in_ptr));
|
||||
} else {
|
||||
r = abs((int) (output - out_ptr));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts PMCH in slot number 1
|
||||
*
|
||||
* Returns the number of symbols written to sf_symbols
|
||||
*
|
||||
* 36.211 10.3 section 6.3.5
|
||||
*/
|
||||
int srslte_pmch_put(srslte_pmch_t *q, cf_t *symbols, cf_t *sf_symbols, uint32_t lstart)
|
||||
{
|
||||
return srslte_pmch_cp(q, symbols, sf_symbols, lstart, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts PMCH from slot number 1
|
||||
*
|
||||
* Returns the number of symbols written to PMCH
|
||||
*
|
||||
* 36.211 10.3 section 6.3.5
|
||||
*/
|
||||
int srslte_pmch_get(srslte_pmch_t *q, cf_t *sf_symbols, cf_t *symbols, uint32_t lstart)
|
||||
{
|
||||
return srslte_pmch_cp(q, sf_symbols, symbols, lstart, false);
|
||||
}
|
||||
|
||||
int srslte_pmch_init(srslte_pmch_t *q, uint32_t max_prb)
|
||||
{
|
||||
return srslte_pmch_init_multi(q, max_prb, 1);
|
||||
}
|
||||
|
||||
int srslte_pmch_init_multi(srslte_pmch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
int i;
|
||||
|
||||
if (q != NULL &&
|
||||
nof_rx_antennas <= SRSLTE_MAX_PORTS)
|
||||
{
|
||||
|
||||
bzero(q, sizeof(srslte_pmch_t));
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
q->cell.nof_prb = max_prb;
|
||||
q->cell.nof_ports = 1;
|
||||
q->max_re = max_prb * MAX_PMCH_RE;
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
|
||||
INFO("Init PMCH: %d PRBs, max_symbols: %d\n",
|
||||
max_prb, q->max_re);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
|
||||
goto clean;
|
||||
}
|
||||
srslte_modem_table_bytes(&q->mod[i]);
|
||||
}
|
||||
|
||||
srslte_sch_init(&q->dl_sch);
|
||||
|
||||
// Allocate int16_t for reception (LLRs)
|
||||
q->e = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
|
||||
if (!q->e) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
q->d = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->d) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->x[i]) {
|
||||
goto clean;
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->ce[i][j]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->symbols[j]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
q->seqs = calloc(SRSLTE_MAX_MBSFN_AREA_IDS, sizeof(srslte_pmch_seq_t*));
|
||||
if (!q->seqs) {
|
||||
perror("calloc");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
clean:
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
srslte_pmch_free(q);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void srslte_pmch_free(srslte_pmch_t *q) {
|
||||
uint16_t i;
|
||||
|
||||
if (q->e) {
|
||||
free(q->e);
|
||||
}
|
||||
if (q->d) {
|
||||
free(q->d);
|
||||
}
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (q->x[i]) {
|
||||
free(q->x[i]);
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
if (q->ce[i][j]) {
|
||||
free(q->ce[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0;i<q->nof_rx_antennas;i++) {
|
||||
if (q->symbols[i]) {
|
||||
free(q->symbols[i]);
|
||||
}
|
||||
}
|
||||
if (q->seqs) {
|
||||
for (i=0; i<SRSLTE_MAX_MBSFN_AREA_IDS; i++) {
|
||||
if (q->seqs[i]) {
|
||||
srslte_pmch_free_area_id(q, i);
|
||||
}
|
||||
}
|
||||
free(q->seqs);
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
srslte_modem_table_free(&q->mod[i]);
|
||||
}
|
||||
|
||||
srslte_sch_free(&q->dl_sch);
|
||||
|
||||
bzero(q, sizeof(srslte_pmch_t));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Precalculate the scramble sequences for a given MBSFN area ID. This function takes a while
|
||||
* to execute.
|
||||
*/
|
||||
int srslte_pmch_set_area_id(srslte_pmch_t *q, uint16_t area_id) {
|
||||
uint32_t i;
|
||||
if (!q->seqs[area_id]) {
|
||||
q->seqs[area_id] = calloc(1, sizeof(srslte_pmch_seq_t));
|
||||
if (q->seqs[area_id]) {
|
||||
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
if (srslte_sequence_pmch(&q->seqs[area_id]->seq[i], 2 * i , area_id, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void srslte_pmch_free_area_id(srslte_pmch_t* q, uint16_t area_id)
|
||||
{
|
||||
if (q->seqs[area_id]) {
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
srslte_sequence_free(&q->seqs[area_id]->seq[i]);
|
||||
}
|
||||
free(q->seqs[area_id]);
|
||||
q->seqs[area_id] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int srslte_pmch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx)
|
||||
{
|
||||
if (cfg) {
|
||||
if (grant) {
|
||||
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
|
||||
}
|
||||
if (srslte_cbsegm(&cfg->cb_segm[0], cfg->grant.mcs[0].tbs)) {
|
||||
fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs[0].tbs);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits);
|
||||
cfg->sf_idx = sf_idx;
|
||||
cfg->rv[0] = SRSLTE_PMCH_RV;
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int srslte_pmch_decode(srslte_pmch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
|
||||
cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate,
|
||||
uint16_t area_id, uint8_t *data)
|
||||
{
|
||||
cf_t *_sf_symbols[SRSLTE_MAX_PORTS];
|
||||
cf_t *_ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
|
||||
_sf_symbols[0] = sf_symbols;
|
||||
for (int i=0;i<q->cell.nof_ports;i++) {
|
||||
_ce[i][0] = ce[i];
|
||||
}
|
||||
return srslte_pmch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, area_id, data);
|
||||
}
|
||||
|
||||
/** Decodes the pmch from the received symbols
|
||||
*/
|
||||
int srslte_pmch_decode_multi(srslte_pmch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
|
||||
cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate,
|
||||
uint16_t area_id, uint8_t *data)
|
||||
{
|
||||
|
||||
/* Set pointers for layermapping & precoding */
|
||||
uint32_t i, n;
|
||||
cf_t *x[SRSLTE_MAX_LAYERS];
|
||||
|
||||
if (q != NULL &&
|
||||
sf_symbols != NULL &&
|
||||
data != NULL &&
|
||||
cfg != NULL)
|
||||
{
|
||||
|
||||
INFO("Decoding PMCH SF: %d, MBSFN area ID: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d, C_prb=%d, cfi=%d\n",
|
||||
cfg->sf_idx, area_id, srslte_mod_string(cfg->grant.mcs[0].mod), cfg->grant.mcs[0].tbs, cfg->nbits[0].nof_re,
|
||||
cfg->nbits[0].nof_bits, 0, cfg->grant.nof_prb, cfg->nbits[0].lstart-1);
|
||||
|
||||
/* number of layers equals number of ports */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
x[i] = q->x[i];
|
||||
}
|
||||
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
|
||||
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
/* extract symbols */
|
||||
n = srslte_pmch_get(q, sf_symbols[j], q->symbols[j], cfg->nbits[0].lstart);
|
||||
if (n != cfg->nbits[0].nof_re) {
|
||||
fprintf(stderr, "PMCH 1 extract symbols error expecting %d symbols but got %d, lstart %d\n", cfg->nbits[0].nof_re, n, cfg->nbits[0].lstart);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
/* extract channel estimates */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
n = srslte_pmch_get(q, ce[i][j], q->ce[i][j], cfg->nbits[0].lstart);
|
||||
if (n != cfg->nbits[0].nof_re) {
|
||||
fprintf(stderr, "PMCH 2 extract chest error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No tx diversity in MBSFN
|
||||
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, noise_estimate);
|
||||
|
||||
if (SRSLTE_VERBOSE_ISDEBUG()) {
|
||||
DEBUG("SAVED FILE subframe.dat: received subframe symbols\n");
|
||||
srslte_vec_save_file("subframe.dat", sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
DEBUG("SAVED FILE hest0.dat: channel estimates for port 4\n");
|
||||
srslte_vec_save_file("hest0.dat", ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
DEBUG("SAVED FILE pmch_symbols.dat: symbols after equalization\n");
|
||||
srslte_vec_save_file("pmch_symbols.bin", q->d, cfg->nbits[0].nof_re*sizeof(cf_t));
|
||||
}
|
||||
|
||||
/* demodulate symbols
|
||||
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
|
||||
* thus we don't need tot set it in thde LLRs normalization
|
||||
*/
|
||||
srslte_demod_soft_demodulate_s(cfg->grant.mcs[0].mod, q->d, q->e, cfg->nbits[0].nof_re);
|
||||
|
||||
/* descramble */
|
||||
srslte_scrambling_s_offset(&q->seqs[area_id]->seq[cfg->sf_idx], q->e, 0, cfg->nbits[0].nof_bits);
|
||||
|
||||
if (SRSLTE_VERBOSE_ISDEBUG()) {
|
||||
DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n");
|
||||
srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t));
|
||||
}
|
||||
return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data);
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
int srslte_pmch_encode(srslte_pmch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
|
||||
uint8_t *data, uint16_t area_id, cf_t *sf_symbols[SRSLTE_MAX_PORTS])
|
||||
{
|
||||
|
||||
int i;
|
||||
/* Set pointers for layermapping & precoding */
|
||||
cf_t *x[SRSLTE_MAX_LAYERS];
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL && cfg != NULL)
|
||||
{
|
||||
for (i=0;i<q->cell.nof_ports;i++) {
|
||||
if (sf_symbols[i] == NULL) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->grant.mcs[0].tbs == 0) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
if (cfg->nbits[0].nof_re > q->max_re) {
|
||||
fprintf(stderr,
|
||||
"Error too many RE per subframe (%d). PMCH configured for %d RE (%d PRB)\n",
|
||||
cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb);
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
INFO("Encoding PMCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
|
||||
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs[0].mod), cfg->grant.mcs[0].tbs,
|
||||
cfg->nbits[0].nof_re, cfg->nbits[0].nof_bits, 0);
|
||||
|
||||
/* number of layers equals number of ports */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
x[i] = q->x[i];
|
||||
}
|
||||
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
|
||||
|
||||
// TODO: use tb_encode directly
|
||||
if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) {
|
||||
fprintf(stderr, "Error encoding TB\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
/* scramble */
|
||||
srslte_scrambling_bytes(&q->seqs[area_id]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits[0].nof_bits);
|
||||
|
||||
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs[0].mod], (uint8_t*) q->e, q->d, cfg->nbits[0].nof_bits);
|
||||
|
||||
/* No tx diversity in MBSFN */
|
||||
memcpy(q->symbols[0], q->d, cfg->nbits[0].nof_re * sizeof(cf_t));
|
||||
|
||||
/* mapping to resource elements */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
srslte_pmch_put(q, q->symbols[i], sf_symbols[i], cfg->nbits[0].lstart);
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t srslte_pmch_last_noi(srslte_pmch_t *q) {
|
||||
return q->dl_sch.nof_iterations;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <srslte/srslte.h>
|
||||
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
#include "srslte/phy/phch/prach.h"
|
||||
|
@ -61,6 +62,8 @@ uint32_t prach_Tseq[5] = {24576, 24576, 2*24576, 2*24576, 4096};
|
|||
// Table 5.7.2-2 - N_cs values for unrestricted sets
|
||||
uint32_t prach_Ncs_unrestricted[16] = {0,13,15,18,22,26,32,38,46,59,76,93,119,167,279,419};
|
||||
|
||||
#define MAX_N_zc 839
|
||||
|
||||
// Table 5.7.2-2 - N_cs values for restricted sets
|
||||
uint32_t prach_Ncs_restricted[15] = {15,18,22,26,32,38,46,55,68,82,100,128,158,202,237};
|
||||
|
||||
|
@ -328,7 +331,10 @@ int srslte_prach_gen_seqs(srslte_prach_t *p)
|
|||
|
||||
int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb)
|
||||
{
|
||||
return srslte_prach_init(p,
|
||||
if (srslte_prach_init(p, srslte_symbol_sz(nof_prb))) {
|
||||
return -1;
|
||||
}
|
||||
return srslte_prach_set_cell(p,
|
||||
srslte_symbol_sz(nof_prb),
|
||||
cfg->config_idx,
|
||||
cfg->root_seq_idx,
|
||||
|
@ -336,28 +342,95 @@ int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t n
|
|||
cfg->zero_corr_zone);
|
||||
}
|
||||
|
||||
int srslte_prach_init(srslte_prach_t *p,
|
||||
uint32_t N_ifft_ul,
|
||||
uint32_t config_idx,
|
||||
uint32_t root_seq_index,
|
||||
bool high_speed_flag,
|
||||
uint32_t zero_corr_zone_config)
|
||||
int srslte_prach_init(srslte_prach_t *p, uint32_t max_N_ifft_ul)
|
||||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
if(p != NULL &&
|
||||
max_N_ifft_ul < 2049)
|
||||
{
|
||||
bzero(p, sizeof(srslte_prach_t));
|
||||
|
||||
p->max_N_ifft_ul = max_N_ifft_ul;
|
||||
|
||||
// Set up containers
|
||||
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc);
|
||||
p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc);
|
||||
p->corr = srslte_vec_malloc(sizeof(float)*MAX_N_zc);
|
||||
|
||||
// Set up ZC FFTS
|
||||
if(srslte_dft_plan(&p->zc_fft, MAX_N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_dft_plan_set_mirror(&p->zc_fft, false);
|
||||
srslte_dft_plan_set_norm(&p->zc_fft, true);
|
||||
|
||||
if(srslte_dft_plan(&p->zc_ifft, MAX_N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_dft_plan_set_mirror(&p->zc_ifft, false);
|
||||
srslte_dft_plan_set_norm(&p->zc_ifft, false);
|
||||
|
||||
uint32_t fft_size_alloc = max_N_ifft_ul * DELTA_F/DELTA_F_RA;
|
||||
|
||||
p->ifft_in = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t));
|
||||
p->ifft_out = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t));
|
||||
if(srslte_dft_plan(&p->ifft, fft_size_alloc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) {
|
||||
fprintf(stderr, "Error creating DFT plan\n");
|
||||
return -1;
|
||||
}
|
||||
srslte_dft_plan_set_mirror(&p->ifft, true);
|
||||
srslte_dft_plan_set_norm(&p->ifft, true);
|
||||
|
||||
if(srslte_dft_plan(&p->fft, fft_size_alloc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
|
||||
fprintf(stderr, "Error creating DFT plan\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->signal_fft = srslte_vec_malloc(sizeof(cf_t)*fft_size_alloc);
|
||||
if (!p->signal_fft) {
|
||||
fprintf(stderr, "Error allocating memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
srslte_dft_plan_set_mirror(&p->fft, true);
|
||||
srslte_dft_plan_set_norm(&p->fft, false);
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid parameters\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int srslte_prach_set_cell(srslte_prach_t *p,
|
||||
uint32_t N_ifft_ul,
|
||||
uint32_t config_idx,
|
||||
uint32_t root_seq_index,
|
||||
bool high_speed_flag,
|
||||
uint32_t zero_corr_zone_config)
|
||||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
if(p != NULL &&
|
||||
N_ifft_ul < 2049 &&
|
||||
config_idx < 64 &&
|
||||
config_idx < 64 &&
|
||||
root_seq_index < MAX_ROOTS)
|
||||
{
|
||||
if (N_ifft_ul > p->max_N_ifft_ul) {
|
||||
fprintf(stderr, "PRACH: Error in set_cell(): N_ifft_ul must be lower or equal max_N_ifft_ul in init()\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t preamble_format = srslte_prach_get_preamble_format(config_idx);
|
||||
p->config_idx = config_idx;
|
||||
p->config_idx = config_idx;
|
||||
p->f = preamble_format;
|
||||
p->rsi = root_seq_index;
|
||||
p->hs = high_speed_flag;
|
||||
p->zczc = zero_corr_zone_config;
|
||||
p->detect_factor = PRACH_DETECT_FACTOR;
|
||||
|
||||
|
||||
p->detect_factor = PRACH_DETECT_FACTOR;
|
||||
|
||||
|
||||
// Determine N_zc and N_cs
|
||||
if(4 == preamble_format){
|
||||
if (p->zczc < 7) {
|
||||
|
@ -368,43 +441,33 @@ int srslte_prach_init(srslte_prach_t *p,
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
}else{
|
||||
p->N_zc = 839;
|
||||
p->N_zc = MAX_N_zc;
|
||||
if(p->hs){
|
||||
if (p->zczc < 15) {
|
||||
p->N_cs = prach_Ncs_restricted[p->zczc];
|
||||
} else {
|
||||
fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d for restricted set\n", p->zczc);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (p->zczc < 16) {
|
||||
p->N_cs = prach_Ncs_unrestricted[p->zczc];
|
||||
} else {
|
||||
fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d\n", p->zczc);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up containers
|
||||
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*p->N_zc);
|
||||
p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*p->N_zc);
|
||||
p->corr = srslte_vec_malloc(sizeof(float)*p->N_zc);
|
||||
|
||||
// Set up ZC FFTS
|
||||
p->zc_fft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
|
||||
if(srslte_dft_plan(p->zc_fft, p->N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
|
||||
return SRSLTE_ERROR;
|
||||
if (p->N_zc != MAX_N_zc) {
|
||||
if(srslte_dft_replan(&p->zc_fft, p->N_zc)){
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if(srslte_dft_replan(&p->zc_ifft, p->N_zc)){
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
srslte_dft_plan_set_mirror(p->zc_fft, false);
|
||||
srslte_dft_plan_set_norm(p->zc_fft, true);
|
||||
|
||||
p->zc_ifft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
|
||||
if(srslte_dft_plan(p->zc_ifft, p->N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_dft_plan_set_mirror(p->zc_ifft, false);
|
||||
srslte_dft_plan_set_norm(p->zc_ifft, false);
|
||||
|
||||
// Generate our 64 sequences
|
||||
p->N_roots = 0;
|
||||
|
@ -412,9 +475,9 @@ int srslte_prach_init(srslte_prach_t *p,
|
|||
|
||||
// Generate sequence FFTs
|
||||
for(int i=0;i<N_SEQS;i++){
|
||||
srslte_dft_run(p->zc_fft, p->seqs[i], p->dft_seqs[i]);
|
||||
srslte_dft_run(&p->zc_fft, p->seqs[i], p->dft_seqs[i]);
|
||||
}
|
||||
|
||||
|
||||
// Create our FFT objects and buffers
|
||||
p->N_ifft_ul = N_ifft_ul;
|
||||
if(4 == preamble_format){
|
||||
|
@ -422,47 +485,31 @@ int srslte_prach_init(srslte_prach_t *p,
|
|||
}else{
|
||||
p->N_ifft_prach = p->N_ifft_ul * DELTA_F/DELTA_F_RA;
|
||||
}
|
||||
|
||||
|
||||
/* The deadzone specifies the number of samples at the end of the correlation window
|
||||
* that will be considered as belonging to the next preamble
|
||||
*/
|
||||
p->deadzone = 0;
|
||||
p->deadzone = 0;
|
||||
/*
|
||||
if(p->N_cs != 0) {
|
||||
float samp_rate=15000*p->N_ifft_ul;
|
||||
p->deadzone = (uint32_t) ceil((float) samp_rate/((float) p->N_zc*subcarrier_spacing));
|
||||
}*/
|
||||
|
||||
p->ifft_in = (cf_t*)srslte_vec_malloc(p->N_ifft_prach*sizeof(cf_t));
|
||||
p->ifft_out = (cf_t*)srslte_vec_malloc(p->N_ifft_prach*sizeof(cf_t));
|
||||
p->ifft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
|
||||
if(srslte_dft_plan(p->ifft, p->N_ifft_prach, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) {
|
||||
if(srslte_dft_replan(&p->ifft, p->N_ifft_prach)) {
|
||||
fprintf(stderr, "Error creating DFT plan\n");
|
||||
return -1;
|
||||
}
|
||||
srslte_dft_plan_set_mirror(p->ifft, true);
|
||||
srslte_dft_plan_set_norm(p->ifft, true);
|
||||
|
||||
p->fft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
|
||||
if(srslte_dft_plan(p->fft, p->N_ifft_prach, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
|
||||
if(srslte_dft_replan(&p->fft, p->N_ifft_prach)){
|
||||
fprintf(stderr, "Error creating DFT plan\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->signal_fft = srslte_vec_malloc(sizeof(cf_t)*p->N_ifft_prach);
|
||||
if (!p->signal_fft) {
|
||||
fprintf(stderr, "Error allocating memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
srslte_dft_plan_set_mirror(p->fft, true);
|
||||
srslte_dft_plan_set_norm(p->fft, false);
|
||||
|
||||
p->N_seq = prach_Tseq[p->f]*p->N_ifft_ul/2048;
|
||||
p->N_cp = prach_Tcp[p->f]*p->N_ifft_ul/2048;
|
||||
p->T_seq = prach_Tseq[p->f]*SRSLTE_LTE_TS;
|
||||
p->T_tot = (prach_Tseq[p->f]+prach_Tcp[p->f])*SRSLTE_LTE_TS;
|
||||
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid parameters\n");
|
||||
|
@ -500,7 +547,7 @@ int srslte_prach_gen(srslte_prach_t *p,
|
|||
memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t));
|
||||
memset(&p->ifft_in[begin+p->N_zc], 0, (p->N_ifft_prach - begin - p->N_zc) * sizeof(cf_t));
|
||||
|
||||
srslte_dft_run(p->ifft, p->ifft_in, p->ifft_out);
|
||||
srslte_dft_run(&p->ifft, p->ifft_in, p->ifft_out);
|
||||
|
||||
// Copy CP into buffer
|
||||
memcpy(signal, &p->ifft_out[p->N_ifft_prach-p->N_cp], p->N_cp*sizeof(cf_t));
|
||||
|
@ -552,7 +599,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
|
|||
}
|
||||
|
||||
// FFT incoming signal
|
||||
srslte_dft_run(p->fft, signal, p->signal_fft);
|
||||
srslte_dft_run(&p->fft, signal, p->signal_fft);
|
||||
|
||||
*n_indices = 0;
|
||||
|
||||
|
@ -569,7 +616,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
|
|||
|
||||
srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc);
|
||||
|
||||
srslte_dft_run(p->zc_ifft, p->corr_spec, p->corr_spec);
|
||||
srslte_dft_run(&p->zc_ifft, p->corr_spec, p->corr_spec);
|
||||
|
||||
srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc);
|
||||
|
||||
|
@ -632,16 +679,12 @@ int srslte_prach_free(srslte_prach_t *p) {
|
|||
free(p->prach_bins);
|
||||
free(p->corr_spec);
|
||||
free(p->corr);
|
||||
srslte_dft_plan_free(p->ifft);
|
||||
free(p->ifft);
|
||||
srslte_dft_plan_free(&p->ifft);
|
||||
free(p->ifft_in);
|
||||
free(p->ifft_out);
|
||||
srslte_dft_plan_free(p->fft);
|
||||
free(p->fft);
|
||||
srslte_dft_plan_free(p->zc_fft);
|
||||
free(p->zc_fft);
|
||||
srslte_dft_plan_free(p->zc_ifft);
|
||||
free(p->zc_ifft);
|
||||
srslte_dft_plan_free(&p->fft);
|
||||
srslte_dft_plan_free(&p->zc_fft);
|
||||
srslte_dft_plan_free(&p->zc_ifft);
|
||||
|
||||
if (p->signal_fft) {
|
||||
free(p->signal_fft);
|
||||
|
|
|
@ -416,37 +416,24 @@ void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1_threshold) {
|
|||
}
|
||||
|
||||
/** Initializes the PDCCH transmitter and receiver */
|
||||
int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
|
||||
int srslte_pucch_init(srslte_pucch_t *q) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q != NULL && srslte_cell_isvalid(&cell)) {
|
||||
if (q != NULL) {
|
||||
ret = SRSLTE_ERROR;
|
||||
bzero(q, sizeof(srslte_pucch_t));
|
||||
|
||||
q->cell = cell;
|
||||
|
||||
srslte_pucch_cfg_default(&q->pucch_cfg);
|
||||
|
||||
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
// Precompute group hopping values u.
|
||||
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
q->users = calloc(sizeof(srslte_pucch_user_t*), 1+SRSLTE_SIRNTI);
|
||||
if (!q->users) {
|
||||
perror("malloc");
|
||||
return SRSLTE_ERROR;
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
srslte_uci_cqi_pucch_init(&q->cqi);
|
||||
|
||||
|
||||
q->z = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
|
||||
q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
|
||||
q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
|
||||
|
@ -455,12 +442,16 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
|
|||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
clean_exit:
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
srslte_pucch_free(q);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void srslte_pucch_free(srslte_pucch_t *q) {
|
||||
if (q->users) {
|
||||
for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) {
|
||||
for (int rnti=0;rnti<=SRSLTE_SIRNTI;rnti++) {
|
||||
srslte_pucch_clear_rnti(q, rnti);
|
||||
}
|
||||
free(q->users);
|
||||
|
@ -480,6 +471,31 @@ void srslte_pucch_free(srslte_pucch_t *q) {
|
|||
bzero(q, sizeof(srslte_pucch_t));
|
||||
}
|
||||
|
||||
int srslte_pucch_set_cell(srslte_pucch_t *q, srslte_cell_t cell) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
if (q != NULL && srslte_cell_isvalid(&cell)) {
|
||||
|
||||
srslte_pucch_cfg_default(&q->pucch_cfg);
|
||||
|
||||
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
|
||||
// Precompute group hopping values u.
|
||||
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) {
|
||||
if (q->users[rnti]) {
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
|
@ -498,6 +514,7 @@ int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t rnti) {
|
|||
// Precompute scrambling sequence for pucch format 2
|
||||
if (srslte_sequence_pucch(&q->users[rnti]->seq_f2[sf_idx], rnti, 2*sf_idx, q->cell.id)) {
|
||||
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n");
|
||||
srslte_pucch_clear_rnti(q, rnti);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <srslte/srslte.h>
|
||||
#include <srslte/phy/phch/pusch.h>
|
||||
|
||||
#include "srslte/phy/ch_estimation/refsignal_ul.h"
|
||||
#include "srslte/phy/phch/pusch.h"
|
||||
|
@ -185,22 +187,18 @@ int pusch_get(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, cf_t *input, cf_t
|
|||
|
||||
|
||||
/** Initializes the PDCCH transmitter and receiver */
|
||||
int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
|
||||
int pusch_init(srslte_pusch_t *q, uint32_t max_prb, bool is_ue) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
int i;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell))
|
||||
if (q != NULL)
|
||||
{
|
||||
|
||||
bzero(q, sizeof(srslte_pusch_t));
|
||||
ret = SRSLTE_ERROR;
|
||||
|
||||
q->cell = cell;
|
||||
q->max_re = q->cell.nof_prb * MAX_PUSCH_RE(q->cell.cp);
|
||||
q->max_re = max_prb * MAX_PUSCH_RE(SRSLTE_CP_NORM);
|
||||
|
||||
INFO("Init PUSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
|
||||
q->cell.nof_prb, q->max_re);
|
||||
INFO("Init PUSCH: %d PRBs\n", max_prb);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
|
||||
|
@ -208,26 +206,26 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
|
|||
}
|
||||
srslte_modem_table_bytes(&q->mod[i]);
|
||||
}
|
||||
|
||||
q->users = calloc(sizeof(srslte_pusch_user_t*), 1+SRSLTE_SIRNTI);
|
||||
|
||||
q->is_ue = is_ue;
|
||||
|
||||
q->users = calloc(sizeof(srslte_pusch_user_t*), q->is_ue?1:(1+SRSLTE_SIRNTI));
|
||||
if (!q->users) {
|
||||
perror("malloc");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
/* Precompute sequence for type2 frequency hopping */
|
||||
if (srslte_sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) {
|
||||
fprintf(stderr, "Error initiating type2 frequency hopping sequence\n");
|
||||
goto clean;
|
||||
if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
srslte_sch_init(&q->ul_sch);
|
||||
|
||||
if (srslte_dft_precoding_init(&q->dft_precoding, cell.nof_prb)) {
|
||||
|
||||
if (srslte_dft_precoding_init(&q->dft_precoding, max_prb, is_ue)) {
|
||||
fprintf(stderr, "Error initiating DFT transform precoding\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
|
||||
// Allocate int16 for reception (LLRs). Buffer casted to uint8_t for transmission
|
||||
q->q = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
|
||||
if (!q->q) {
|
||||
|
@ -244,9 +242,11 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
|
|||
goto clean;
|
||||
}
|
||||
|
||||
q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->ce) {
|
||||
goto clean;
|
||||
if (!q->is_ue) {
|
||||
q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->ce) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
q->z = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->z) {
|
||||
|
@ -262,6 +262,14 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int srslte_pusch_init_ue(srslte_pusch_t *q, uint32_t max_prb) {
|
||||
return pusch_init(q, max_prb, true);
|
||||
}
|
||||
|
||||
int srslte_pusch_init_enb(srslte_pusch_t *q, uint32_t max_prb) {
|
||||
return pusch_init(q, max_prb, false);
|
||||
}
|
||||
|
||||
void srslte_pusch_free(srslte_pusch_t *q) {
|
||||
int i;
|
||||
|
||||
|
@ -284,13 +292,20 @@ void srslte_pusch_free(srslte_pusch_t *q) {
|
|||
srslte_dft_precoding_free(&q->dft_precoding);
|
||||
|
||||
if (q->users) {
|
||||
for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) {
|
||||
srslte_pusch_clear_rnti(q, rnti);
|
||||
if (q->is_ue) {
|
||||
srslte_pusch_free_rnti(q, 0);
|
||||
} else {
|
||||
for (int rnti=0;rnti<=SRSLTE_SIRNTI;rnti++) {
|
||||
srslte_pusch_free_rnti(q, rnti);
|
||||
}
|
||||
}
|
||||
free(q->users);
|
||||
}
|
||||
|
||||
srslte_sequence_free(&q->seq_type2_fo);
|
||||
|
||||
srslte_sequence_free(&q->tmp_seq);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
srslte_modem_table_free(&q->mod[i]);
|
||||
}
|
||||
|
@ -300,6 +315,33 @@ void srslte_pusch_free(srslte_pusch_t *q) {
|
|||
|
||||
}
|
||||
|
||||
int srslte_pusch_set_cell(srslte_pusch_t *q, srslte_cell_t cell) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL && srslte_cell_isvalid(&cell))
|
||||
{
|
||||
|
||||
q->max_re = cell.nof_prb * MAX_PUSCH_RE(q->cell.cp);
|
||||
|
||||
INFO("PUSCH: Cell config PCI=%d, %d ports %d PRBs, max_symbols: %d\n",
|
||||
q->cell.id, q->cell.nof_ports, q->cell.nof_prb, q->max_re);
|
||||
|
||||
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
|
||||
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
|
||||
/* Precompute sequence for type2 frequency hopping */
|
||||
if (srslte_sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) {
|
||||
fprintf(stderr, "Error initiating type2 frequency hopping sequence\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Configures the structure srslte_pusch_cfg_t from the UL DCI allocation dci_msg.
|
||||
* If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
|
||||
*/
|
||||
|
@ -391,29 +433,63 @@ int srslte_pusch_cfg(srslte_pusch_t *q,
|
|||
* For the connection procedure, use srslte_pusch_encode() functions */
|
||||
int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) {
|
||||
uint32_t i;
|
||||
|
||||
if (!q->users[rnti]) {
|
||||
q->users[rnti] = calloc(1, sizeof(srslte_pusch_user_t));
|
||||
if (q->users[rnti]) {
|
||||
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
if (srslte_sequence_pusch(&q->users[rnti]->seq[i], rnti, 2 * i, q->cell.id,
|
||||
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
uint32_t rnti_idx = q->is_ue?0:rnti;
|
||||
|
||||
if (!q->users[rnti_idx] || q->is_ue) {
|
||||
if (!q->users[rnti_idx]) {
|
||||
q->users[rnti_idx] = calloc(1, sizeof(srslte_pusch_user_t));
|
||||
if (!q->users[rnti_idx]) {
|
||||
perror("calloc");
|
||||
return -1;
|
||||
}
|
||||
q->users[rnti]->sequences_generated = true;
|
||||
}
|
||||
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
if (srslte_sequence_pusch(&q->users[rnti_idx]->seq[i], rnti, 2 * i, q->cell.id,
|
||||
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)))
|
||||
{
|
||||
fprintf(stderr, "Error initializing PUSCH scrambling sequence\n");
|
||||
srslte_pusch_free_rnti(q, rnti);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
q->ue_rnti = rnti;
|
||||
q->users[rnti_idx]->cell_id = q->cell.id;
|
||||
q->users[rnti_idx]->sequence_generated = true;
|
||||
} else {
|
||||
fprintf(stderr, "Error generating PUSCH sequence: rnti=0x%x already generated\n", rnti);
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void srslte_pusch_clear_rnti(srslte_pusch_t *q, uint16_t rnti) {
|
||||
if (q->users[rnti]) {
|
||||
void srslte_pusch_free_rnti(srslte_pusch_t *q, uint16_t rnti) {
|
||||
|
||||
uint32_t rnti_idx = q->is_ue?0:rnti;
|
||||
|
||||
if (q->users[rnti_idx]) {
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
srslte_sequence_free(&q->users[rnti]->seq[i]);
|
||||
srslte_sequence_free(&q->users[rnti_idx]->seq[i]);
|
||||
}
|
||||
free(q->users[rnti]);
|
||||
q->users[rnti] = NULL;
|
||||
free(q->users[rnti_idx]);
|
||||
q->users[rnti_idx] = NULL;
|
||||
q->ue_rnti = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static srslte_sequence_t *get_user_sequence(srslte_pusch_t *q, uint16_t rnti, uint32_t sf_idx, uint32_t len)
|
||||
{
|
||||
uint32_t rnti_idx = q->is_ue?0:rnti;
|
||||
|
||||
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
|
||||
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated &&
|
||||
q->users[rnti_idx]->cell_id == q->cell.id &&
|
||||
q->ue_rnti == rnti &&
|
||||
((rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) || !q->is_ue))
|
||||
{
|
||||
return &q->users[rnti_idx]->seq[sf_idx];
|
||||
} else {
|
||||
srslte_sequence_pusch(&q->tmp_seq, rnti, 2 * sf_idx, q->cell.id, len);
|
||||
return &q->tmp_seq;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,18 +521,13 @@ int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softb
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (q->users[rnti] && q->users[rnti]->sequences_generated) {
|
||||
srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits);
|
||||
} else {
|
||||
srslte_sequence_t seq;
|
||||
if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
|
||||
// Correct UCI placeholder/repetition bits
|
||||
// Generate scrambling sequence if not pre-generated
|
||||
srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
|
||||
|
||||
// Run scrambling
|
||||
srslte_scrambling_bytes(seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
|
||||
|
||||
// Correct UCI placeholder/repetition bits
|
||||
uint8_t *d = q->q;
|
||||
for (int i = 0; i < q->ul_sch.nof_ri_ack_bits; i++) {
|
||||
if (q->ul_sch.ack_ri_bits[i].type == UCI_BIT_PLACEHOLDER) {
|
||||
|
@ -528,24 +599,15 @@ int srslte_pusch_decode(srslte_pusch_t *q,
|
|||
srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate);
|
||||
|
||||
// DFT predecoding
|
||||
srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb);
|
||||
srslte_dft_precoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb);
|
||||
|
||||
// Soft demodulation
|
||||
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re);
|
||||
|
||||
srslte_sequence_t *seq = NULL;
|
||||
// Generate scrambling sequence if not pre-generated
|
||||
srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
|
||||
|
||||
// Create sequence if does not exist
|
||||
if (q->users[rnti] && q->users[rnti]->sequences_generated) {
|
||||
seq = &q->users[rnti]->seq[cfg->sf_idx];
|
||||
} else {
|
||||
seq = &q->tmp_seq;
|
||||
if (srslte_sequence_pusch(seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Decode RI/HARQ bits before descrambling
|
||||
// Decode RI/HARQ bits before descrambling
|
||||
if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) {
|
||||
fprintf(stderr, "Error decoding RI/HARQ bits\n");
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -554,11 +616,7 @@ int srslte_pusch_decode(srslte_pusch_t *q,
|
|||
// Descrambling
|
||||
srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits);
|
||||
|
||||
if (!(q->users[rnti] && q->users[rnti]->sequences_generated)) {
|
||||
srslte_sequence_free(seq);
|
||||
}
|
||||
|
||||
return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data);
|
||||
return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data);
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
|
|
@ -41,15 +41,19 @@
|
|||
|
||||
/* Returns the number of RE in a PRB in a slot and subframe */
|
||||
uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_t nof_prb,
|
||||
uint32_t nof_ports, uint32_t nof_ctrl_symbols, srslte_cp_t cp) {
|
||||
uint32_t nof_ports, uint32_t nof_ctrl_symbols, srslte_cp_t cp, srslte_sf_t sf_type) {
|
||||
|
||||
uint32_t re;
|
||||
bool skip_refs = false;
|
||||
bool skip_refs = true;
|
||||
srslte_cp_t cp_ = cp;
|
||||
if(SRSLTE_SF_MBSFN == sf_type) {
|
||||
cp_ = SRSLTE_CP_EXT;
|
||||
}
|
||||
|
||||
if (slot == 0) {
|
||||
re = (SRSLTE_CP_NSYMB(cp) - nof_ctrl_symbols) * SRSLTE_NRE;
|
||||
re = (SRSLTE_CP_NSYMB(cp_) - nof_ctrl_symbols) * SRSLTE_NRE;
|
||||
} else {
|
||||
re = SRSLTE_CP_NSYMB(cp) * SRSLTE_NRE;
|
||||
re = SRSLTE_CP_NSYMB(cp_) * SRSLTE_NRE;
|
||||
}
|
||||
|
||||
/* if it's the prb in the middle, there are less RE due to PBCH and PSS/SSS */
|
||||
|
@ -57,18 +61,18 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_
|
|||
&& (prb_idx >= nof_prb / 2 - 3 && prb_idx < nof_prb / 2 + 3 + (nof_prb%2))) {
|
||||
if (subframe == 0) {
|
||||
if (slot == 0) {
|
||||
re = (SRSLTE_CP_NSYMB(cp) - nof_ctrl_symbols - 2) * SRSLTE_NRE;
|
||||
re = (SRSLTE_CP_NSYMB(cp_) - nof_ctrl_symbols - 2) * SRSLTE_NRE;
|
||||
} else {
|
||||
if (SRSLTE_CP_ISEXT(cp)) {
|
||||
re = (SRSLTE_CP_NSYMB(cp) - 4) * SRSLTE_NRE;
|
||||
skip_refs = true;
|
||||
if (SRSLTE_CP_ISEXT(cp_)) {
|
||||
re = (SRSLTE_CP_NSYMB(cp_) - 4) * SRSLTE_NRE;
|
||||
skip_refs = false;
|
||||
} else {
|
||||
re = (SRSLTE_CP_NSYMB(cp) - 4) * SRSLTE_NRE + 2 * nof_ports;
|
||||
re = (SRSLTE_CP_NSYMB(cp_) - 4) * SRSLTE_NRE + 2 * nof_ports;
|
||||
}
|
||||
}
|
||||
} else if (subframe == 5) {
|
||||
if (slot == 0) {
|
||||
re = (SRSLTE_CP_NSYMB(cp) - nof_ctrl_symbols - 2) * SRSLTE_NRE;
|
||||
re = (SRSLTE_CP_NSYMB(cp_) - nof_ctrl_symbols - 2) * SRSLTE_NRE;
|
||||
}
|
||||
}
|
||||
if ((nof_prb % 2)
|
||||
|
@ -77,7 +81,7 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_
|
|||
re += 2 * SRSLTE_NRE / 2;
|
||||
} else if (subframe == 0) {
|
||||
re += 4 * SRSLTE_NRE / 2 - nof_ports;
|
||||
if (SRSLTE_CP_ISEXT(cp)) {
|
||||
if (SRSLTE_CP_ISEXT(cp_)) {
|
||||
re -= nof_ports > 2 ? 2 : nof_ports;
|
||||
}
|
||||
}
|
||||
|
@ -85,22 +89,27 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_
|
|||
}
|
||||
|
||||
// remove references
|
||||
if (!skip_refs) {
|
||||
switch (nof_ports) {
|
||||
case 1:
|
||||
case 2:
|
||||
re -= 2 * (slot + 1) * nof_ports;
|
||||
break;
|
||||
case 4:
|
||||
if (slot == 1) {
|
||||
re -= 12;
|
||||
} else {
|
||||
re -= 4;
|
||||
if (nof_ctrl_symbols == 1) {
|
||||
if (skip_refs) {
|
||||
if(sf_type == SRSLTE_SF_NORM){
|
||||
switch (nof_ports) {
|
||||
case 1:
|
||||
case 2:
|
||||
re -= 2 * (slot + 1) * nof_ports;
|
||||
break;
|
||||
case 4:
|
||||
if (slot == 1) {
|
||||
re -= 12;
|
||||
} else {
|
||||
re -= 4;
|
||||
if (nof_ctrl_symbols == 1) {
|
||||
re -= 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(sf_type == SRSLTE_SF_MBSFN){
|
||||
re -= 6*(slot + 1);
|
||||
}
|
||||
}
|
||||
return re;
|
||||
|
@ -278,23 +287,23 @@ uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32
|
|||
|
||||
/* Computes the number of RE for each PRB in the prb_dist structure */
|
||||
uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell,
|
||||
uint32_t sf_idx, uint32_t nof_ctrl_symbols)
|
||||
uint32_t sf_idx, uint32_t nof_ctrl_symbols)
|
||||
{
|
||||
uint32_t j, s;
|
||||
|
||||
// Compute number of RE per PRB
|
||||
uint32_t nof_re = 0;
|
||||
for (s = 0; s < 2; s++) {
|
||||
for (j = 0; j < cell.nof_prb; j++) {
|
||||
if (grant->prb_idx[s][j]) {
|
||||
nof_re += ra_re_x_prb(sf_idx, s, j,
|
||||
cell.nof_prb, cell.nof_ports, nof_ctrl_symbols, cell.cp);
|
||||
nof_re += ra_re_x_prb(sf_idx, s, j, cell.nof_prb, cell.nof_ports,
|
||||
nof_ctrl_symbols, cell.cp, grant->sf_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nof_re;
|
||||
}
|
||||
|
||||
|
||||
/** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213
|
||||
* Decode dci->type?_alloc to grant
|
||||
* This function only reads dci->type?_alloc and dci->alloc_type fields.
|
||||
|
@ -432,7 +441,7 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) {
|
||||
int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) {
|
||||
uint32_t i_tbs = 0;
|
||||
int tbs = -1;
|
||||
if (mcs->idx < 10) {
|
||||
|
@ -457,6 +466,53 @@ int dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) {
|
|||
tbs = 0;
|
||||
i_tbs = 0;
|
||||
}
|
||||
|
||||
if (tbs == -1) {
|
||||
tbs = srslte_ra_tbs_from_idx(i_tbs, nprb);
|
||||
if (tbs >= 0) {
|
||||
mcs->tbs = tbs;
|
||||
}
|
||||
}
|
||||
return tbs;
|
||||
}
|
||||
|
||||
int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) {
|
||||
uint32_t i_tbs = 0;
|
||||
int tbs = -1;
|
||||
if (mcs->idx < 5) {
|
||||
mcs->mod = SRSLTE_MOD_QPSK;
|
||||
i_tbs = mcs->idx*2;
|
||||
}else if (mcs->idx < 6) {
|
||||
mcs->mod = SRSLTE_MOD_16QAM;
|
||||
i_tbs = mcs->idx*2;
|
||||
}else if (mcs->idx < 11) {
|
||||
mcs->mod = SRSLTE_MOD_16QAM;
|
||||
i_tbs = mcs->idx + 5;
|
||||
}else if (mcs->idx < 20) {
|
||||
mcs->mod = SRSLTE_MOD_64QAM;
|
||||
i_tbs = mcs->idx + 5;
|
||||
}else if (mcs->idx < 28) {
|
||||
//mcs->mod = SRSLTE_MOD_256QAM;
|
||||
i_tbs = mcs->idx + 5;
|
||||
}else if (mcs->idx == 28) {
|
||||
mcs->mod = SRSLTE_MOD_QPSK;
|
||||
tbs = 0;
|
||||
i_tbs = 0;
|
||||
}else if (mcs->idx == 29) {
|
||||
mcs->mod = SRSLTE_MOD_16QAM;
|
||||
tbs = 0;
|
||||
i_tbs = 0;
|
||||
}else if (mcs->idx == 30) {
|
||||
mcs->mod = SRSLTE_MOD_64QAM;
|
||||
tbs = 0;
|
||||
i_tbs = 0;
|
||||
}else if (mcs->idx == 31) {
|
||||
mcs->mod = SRSLTE_MOD_64QAM;
|
||||
tbs = 0;
|
||||
i_tbs = 0;
|
||||
}
|
||||
|
||||
|
||||
if (tbs == -1) {
|
||||
tbs = srslte_ra_tbs_from_idx(i_tbs, nprb);
|
||||
if (tbs >= 0) {
|
||||
|
@ -496,21 +552,23 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
|
|||
grant->mcs[0].tbs = (uint32_t) tbs;
|
||||
} else {
|
||||
n_prb = grant->nof_prb;
|
||||
grant->nof_tb = 0;
|
||||
if (dci->tb_en[0]) {
|
||||
grant->mcs[0].idx = dci->mcs_idx;
|
||||
tbs = dl_fill_ra_mcs(&grant->mcs[0], n_prb);
|
||||
tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb);
|
||||
if (tbs) {
|
||||
last_dl_tbs[dci->harq_process%8] = tbs;
|
||||
} else {
|
||||
// For mcs>=29, set last TBS received for this PID
|
||||
grant->mcs[0].tbs = last_dl_tbs[dci->harq_process%8];
|
||||
}
|
||||
grant->nof_tb++;
|
||||
} else {
|
||||
grant->mcs[0].tbs = 0;
|
||||
}
|
||||
if (dci->tb_en[1]) {
|
||||
grant->mcs[1].idx = dci->mcs_idx_1;
|
||||
tbs = dl_fill_ra_mcs(&grant->mcs[1], n_prb);
|
||||
tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb);
|
||||
if (tbs) {
|
||||
last_dl_tbs2[dci->harq_process%8] = tbs;
|
||||
} else {
|
||||
|
@ -521,11 +579,10 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
|
|||
grant->mcs[1].tbs = 0;
|
||||
}
|
||||
}
|
||||
grant->nof_tb = 0;
|
||||
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||
grant->tb_en[tb] = dci->tb_en[tb];
|
||||
if (dci->tb_en[tb]) {
|
||||
grant->Qm[tb] = srslte_mod_bits_x_symbol(grant->mcs[tb].mod);
|
||||
grant->nof_tb++;
|
||||
}
|
||||
}
|
||||
grant->pinfo = dci->pinfo;
|
||||
|
@ -541,19 +598,26 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl
|
|||
srslte_ra_nbits_t nbits [SRSLTE_MAX_CODEWORDS])
|
||||
{
|
||||
// Compute number of RE
|
||||
for (int i = 0; i < grant->nof_tb; i++) {
|
||||
/* Compute number of RE for first transport block */
|
||||
nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
|
||||
nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
|
||||
nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart;
|
||||
nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i];
|
||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
if (grant->tb_en[i]) {
|
||||
/* Compute number of RE for first transport block */
|
||||
nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
|
||||
nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
|
||||
if (SRSLTE_SF_NORM == grant->sf_type) {
|
||||
nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart;
|
||||
} else if (SRSLTE_SF_MBSFN == grant->sf_type) {
|
||||
nbits[i].nof_symb = 2 * SRSLTE_CP_EXT_NSYMB - nbits[0].lstart;
|
||||
}
|
||||
nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Obtains a DL grant from a DCI grant for PDSCH */
|
||||
int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
|
||||
uint32_t nof_prb, uint16_t msg_rnti, srslte_ra_dl_grant_t *grant)
|
||||
{
|
||||
{
|
||||
grant->sf_type = SRSLTE_SF_NORM;
|
||||
bool crc_is_crnti = false;
|
||||
if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) {
|
||||
crc_is_crnti = true;
|
||||
|
@ -820,11 +884,13 @@ void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_dl_dci_t *dci, uint32_t nof_prb)
|
|||
void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
|
||||
srslte_ra_prb_fprint(f, grant);
|
||||
fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb);
|
||||
fprintf(f, " - Number of TBs:\t\t\t%d\n", grant->nof_tb);
|
||||
for (int i = 0; i < grant->nof_tb; i++) {
|
||||
fprintf(f, " - Transport block:\t\t\t%d\n", i);
|
||||
fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod));
|
||||
fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs);
|
||||
fprintf(f, " - Number of TBs:\t\t\t%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(grant));
|
||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
if (grant->tb_en[i]) {
|
||||
fprintf(f, " - Transport block:\t\t\t%d\n", i);
|
||||
fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod));
|
||||
fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -841,6 +907,4 @@ void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -32,12 +32,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "srslte/phy/phch/pdsch.h"
|
||||
#include "srslte/phy/phch/pusch.h"
|
||||
#include "srslte/phy/phch/sch.h"
|
||||
#include "srslte/phy/phch/uci.h"
|
||||
#include "srslte/phy/common/phy_common.h"
|
||||
#include "srslte/phy/utils/bit.h"
|
||||
#include "srslte/phy/utils/debug.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
|
@ -174,15 +169,10 @@ void srslte_sch_set_max_noi(srslte_sch_t *q, uint32_t max_iterations) {
|
|||
q->max_iterations = max_iterations;
|
||||
}
|
||||
|
||||
float srslte_sch_average_noi(srslte_sch_t *q) {
|
||||
return q->average_nof_iterations;
|
||||
}
|
||||
|
||||
uint32_t srslte_sch_last_noi(srslte_sch_t *q) {
|
||||
return q->nof_iterations;
|
||||
}
|
||||
|
||||
|
||||
/* Encode a transport block according to 36.212 5.3.2
|
||||
*
|
||||
*/
|
||||
|
@ -320,8 +310,8 @@ bool decode_tb_cb(srslte_sch_t *q,
|
|||
|
||||
bool cb_map[SRSLTE_MAX_CODEBLOCKS];
|
||||
|
||||
uint32_t cb_idx[SRSLTE_TDEC_NPAR];
|
||||
int16_t *decoder_input[SRSLTE_TDEC_NPAR];
|
||||
uint32_t cb_idx[SRSLTE_TDEC_MAX_NPAR];
|
||||
int16_t *decoder_input[SRSLTE_TDEC_MAX_NPAR];
|
||||
|
||||
uint32_t nof_cb = cb_size_group?cb_segm->C2:cb_segm->C1;
|
||||
uint32_t first_cb = cb_size_group?cb_segm->C1:0;
|
||||
|
@ -338,9 +328,9 @@ bool decode_tb_cb(srslte_sch_t *q,
|
|||
return false;
|
||||
}
|
||||
|
||||
for (int i=0;i<SRSLTE_TDEC_NPAR;i++) {
|
||||
for (int i=0;i<srslte_tdec_get_nof_parallel(&q->decoder);i++) {
|
||||
cb_idx[i] = i+first_cb;
|
||||
decoder_input[i] = false;
|
||||
decoder_input[i] = NULL;
|
||||
}
|
||||
|
||||
for (int i=0;i<nof_cb;i++) {
|
||||
|
@ -349,12 +339,14 @@ bool decode_tb_cb(srslte_sch_t *q,
|
|||
|
||||
srslte_tdec_reset(&q->decoder, cb_len);
|
||||
|
||||
uint32_t remaining_cb = nof_cb;
|
||||
|
||||
uint32_t remaining_cb = nof_cb;
|
||||
|
||||
q->nof_iterations = 0;
|
||||
|
||||
while(remaining_cb>0) {
|
||||
|
||||
// Unratematch the codeblocks left to decode
|
||||
for (int i=0;i<SRSLTE_TDEC_NPAR;i++) {
|
||||
for (int i=0;i<srslte_tdec_get_nof_parallel(&q->decoder);i++) {
|
||||
|
||||
if (!decoder_input[i] && remaining_cb > 0) {
|
||||
// Find an unprocessed CB
|
||||
|
@ -372,25 +364,23 @@ bool decode_tb_cb(srslte_sch_t *q,
|
|||
n_e2 = n_e+Qm;
|
||||
rp = (cb_segm->C - gamma)*n_e + (cb_idx[i]-(cb_segm->C - gamma))*n_e2;
|
||||
}
|
||||
|
||||
|
||||
INFO("CB %d: rp=%d, n_e=%d, i=%d\n", cb_idx[i], rp, n_e2, i);
|
||||
if (srslte_rm_turbo_rx_lut(&e_bits[rp], softbuffer->buffer_f[cb_idx[i]], n_e2, cb_len_idx, rv)) {
|
||||
fprintf(stderr, "Error in rate matching\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
decoder_input[i] = softbuffer->buffer_f[cb_idx[i]];
|
||||
decoder_input[i] = softbuffer->buffer_f[cb_idx[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run 1 iteration for up to TDEC_NPAR codeblocks
|
||||
// Run 1 iteration for the codeblocks in queue
|
||||
srslte_tdec_iteration_par(&q->decoder, decoder_input, cb_len);
|
||||
|
||||
q->nof_iterations = srslte_tdec_get_nof_iterations_cb(&q->decoder, 0);
|
||||
|
||||
// Decide output bits and compute CRC
|
||||
for (int i=0;i<SRSLTE_TDEC_NPAR;i++) {
|
||||
for (int i=0;i<srslte_tdec_get_nof_parallel(&q->decoder);i++) {
|
||||
if (decoder_input[i]) {
|
||||
srslte_tdec_decision_byte_par_cb(&q->decoder, q->cb_in, i, cb_len);
|
||||
|
||||
|
@ -409,24 +399,30 @@ bool decode_tb_cb(srslte_sch_t *q,
|
|||
if (!srslte_crc_checksum_byte(crc_ptr, q->cb_in, len_crc)) {
|
||||
|
||||
memcpy(&data[(cb_idx[i]*rlen)/8], q->cb_in, rlen/8 * sizeof(uint8_t));
|
||||
|
||||
|
||||
q->nof_iterations += srslte_tdec_get_nof_iterations_cb(&q->decoder, i);
|
||||
|
||||
// Reset number of iterations for that CB in the decoder
|
||||
srslte_tdec_reset_cb(&q->decoder, i);
|
||||
remaining_cb--;
|
||||
decoder_input[i] = NULL;
|
||||
cb_idx[i] = 0;
|
||||
|
||||
// CRC is error and exceeded maximum iterations for this CB.
|
||||
|
||||
// CRC is error and exceeded maximum iterations for this CB.
|
||||
// Early stop the whole transport block.
|
||||
} else if (srslte_tdec_get_nof_iterations_cb(&q->decoder, i) >= q->max_iterations) {
|
||||
INFO("CB %d: Error. CB is erroneous. remaining_cb=%d, i=%d, first_cb=%d, nof_cb=%d\n",
|
||||
cb_idx[i], remaining_cb, i, first_cb, nof_cb);
|
||||
return false;
|
||||
cb_idx[i], remaining_cb, i, first_cb, nof_cb);
|
||||
|
||||
q->nof_iterations += q->max_iterations;
|
||||
q->nof_iterations /= (nof_cb-remaining_cb+1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
q->nof_iterations /= nof_cb;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -478,7 +474,7 @@ static int decode_tb(srslte_sch_t *q,
|
|||
data[cb_segm->tbs/8+1] = 0;
|
||||
data[cb_segm->tbs/8+2] = 0;
|
||||
|
||||
// Process Codeblocks in groups of equal CB size to parallelize according to SRSLTE_TDEC_NPAR
|
||||
// Process Codeblocks in groups of equal CB size to parallelize according to SRSLTE_TDEC_MAX_NPAR
|
||||
for (uint32_t i=0;i<nof_cb_groups && crc_ok;i++) {
|
||||
crc_ok = decode_tb_cb(q, softbuffer, cb_segm, Qm, rv, nof_e_bits, e_bits, data, i);
|
||||
}
|
||||
|
@ -524,7 +520,7 @@ int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu
|
|||
int16_t *e_bits, uint8_t *data, int codeword_idx) {
|
||||
uint32_t Nl = 1;
|
||||
|
||||
if (cfg->nof_layers != cfg->grant.nof_tb) {
|
||||
if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) {
|
||||
Nl = 2;
|
||||
}
|
||||
|
||||
|
@ -553,7 +549,7 @@ int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu
|
|||
uint8_t *data, uint8_t *e_bits, int codeword_idx) {
|
||||
uint32_t Nl = 1;
|
||||
|
||||
if (cfg->nof_layers != cfg->grant.nof_tb) {
|
||||
if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) {
|
||||
Nl = 2;
|
||||
}
|
||||
|
||||
|
@ -657,14 +653,17 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs
|
|||
|
||||
// Deinterleave and decode HARQ bits
|
||||
if (uci_data->uci_ack_len > 0) {
|
||||
uint8_t acks[2] = {0, 0};
|
||||
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
|
||||
if (cfg->cb_segm.tbs == 0) {
|
||||
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
|
||||
}
|
||||
ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ack);
|
||||
ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
uci_data->uci_ack = acks[0];
|
||||
uci_data->uci_ack_2 = acks[1];
|
||||
Q_prime_ack = (uint32_t) ret;
|
||||
|
||||
// Set zeros to HARQ bits
|
||||
|
@ -805,11 +804,13 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
|
|||
|
||||
// Encode (and interleave) ACK
|
||||
if (uci_data.uci_ack_len > 0) {
|
||||
uint8_t acks [2] = {uci_data.uci_ack, uci_data.uci_ack_2};
|
||||
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
|
||||
if (cfg->cb_segm.tbs == 0) {
|
||||
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
|
||||
}
|
||||
ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, &q->ack_ri_bits[Q_prime_ri*Qm]);
|
||||
ret = srslte_uci_encode_ack(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len,
|
||||
beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
* 36.211 6.6.1
|
||||
*/
|
||||
int srslte_sequence_pbch(srslte_sequence_t *seq, srslte_cp_t cp, uint32_t cell_id) {
|
||||
bzero(seq, sizeof(srslte_sequence_t));
|
||||
return srslte_sequence_LTE_pr(seq, SRSLTE_CP_ISNORM(cp)?1920:1728, cell_id);
|
||||
}
|
||||
|
||||
|
@ -41,7 +40,6 @@ int srslte_sequence_pbch(srslte_sequence_t *seq, srslte_cp_t cp, uint32_t cell_i
|
|||
* 36.211 6.7.1
|
||||
*/
|
||||
int srslte_sequence_pcfich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id) {
|
||||
bzero(seq, sizeof(srslte_sequence_t));
|
||||
return srslte_sequence_LTE_pr(seq, 32, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id);
|
||||
}
|
||||
|
||||
|
@ -50,7 +48,6 @@ int srslte_sequence_pcfich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell
|
|||
* 36.211 6.9.1
|
||||
*/
|
||||
int srslte_sequence_phich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id) {
|
||||
bzero(seq, sizeof(srslte_sequence_t));
|
||||
return srslte_sequence_LTE_pr(seq, 12, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id);
|
||||
}
|
||||
|
||||
|
@ -58,7 +55,6 @@ int srslte_sequence_phich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_
|
|||
* 36.211 6.8.2
|
||||
*/
|
||||
int srslte_sequence_pdcch(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id, uint32_t len) {
|
||||
bzero(seq, sizeof(srslte_sequence_t));
|
||||
return srslte_sequence_LTE_pr(seq, len, (nslot/2) * 512 + cell_id);
|
||||
}
|
||||
|
||||
|
@ -66,7 +62,6 @@ int srslte_sequence_pdcch(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_
|
|||
* 36.211 6.3.1
|
||||
*/
|
||||
int srslte_sequence_pdsch(srslte_sequence_t *seq, uint16_t rnti, int q, uint32_t nslot, uint32_t cell_id, uint32_t len) {
|
||||
bzero(seq, sizeof(srslte_sequence_t));
|
||||
return srslte_sequence_LTE_pr(seq, len, (rnti<<14) + (q<<13) + ((nslot/2)<<9) + cell_id);
|
||||
}
|
||||
|
||||
|
@ -74,7 +69,6 @@ int srslte_sequence_pdsch(srslte_sequence_t *seq, uint16_t rnti, int q, uint32_t
|
|||
* 36.211 5.3.1
|
||||
*/
|
||||
int srslte_sequence_pusch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id, uint32_t len) {
|
||||
bzero(seq, sizeof(srslte_sequence_t));
|
||||
return srslte_sequence_LTE_pr(seq, len, (rnti<<14) + ((nslot/2)<<9) + cell_id);
|
||||
}
|
||||
|
||||
|
@ -82,6 +76,11 @@ int srslte_sequence_pusch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot,
|
|||
* 36.211 5.4.2
|
||||
*/
|
||||
int srslte_sequence_pucch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id) {
|
||||
bzero(seq, sizeof(srslte_sequence_t));
|
||||
return srslte_sequence_LTE_pr(seq, 20, ((((nslot/2)+1)*(2*cell_id+1))<<16)+rnti);
|
||||
}
|
||||
|
||||
int srslte_sequence_pmch(srslte_sequence_t *seq, uint32_t nslot, uint32_t mbsfn_id , uint32_t len){
|
||||
bzero(seq,sizeof(srslte_sequence_t));
|
||||
return srslte_sequence_LTE_pr(seq, len, (((nslot/2)<<9) + mbsfn_id));
|
||||
|
||||
}
|
|
@ -159,6 +159,19 @@ add_test(pdsch_test_multiplex2cw_p1_50 pdsch_test -x multiplex -a 2 -t 0 -p 1 -
|
|||
add_test(pdsch_test_multiplex2cw_p1_75 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 75)
|
||||
add_test(pdsch_test_multiplex2cw_p1_100 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 100)
|
||||
|
||||
########################################################################
|
||||
# PMCH TEST
|
||||
########################################################################
|
||||
|
||||
|
||||
add_executable(pmch_test pmch_test.c)
|
||||
target_link_libraries(pmch_test srslte_phy)
|
||||
|
||||
add_test(pmch_test_qpsk pmch_test -m 6 -n 50)
|
||||
add_test(pmch_test_qam16 pmch_test -m 15 -n 100)
|
||||
add_test(pmch_test_qam64 pmch_test -m 25 -n 100)
|
||||
|
||||
|
||||
########################################################################
|
||||
# FILE TEST
|
||||
########################################################################
|
||||
|
@ -178,11 +191,15 @@ target_link_libraries(pdcch_file_test srslte_phy)
|
|||
add_executable(pdsch_pdcch_file_test pdsch_pdcch_file_test.c)
|
||||
target_link_libraries(pdsch_pdcch_file_test srslte_phy)
|
||||
|
||||
add_executable(pmch_file_test pmch_file_test.c)
|
||||
target_link_libraries(pmch_file_test srslte_phy)
|
||||
|
||||
add_test(pbch_file_test pbch_file_test -i ${CMAKE_CURRENT_SOURCE_DIR}/signal.1.92M.dat)
|
||||
add_test(pcfich_file_test pcfich_file_test -c 150 -n 50 -p 2 -i ${CMAKE_CURRENT_SOURCE_DIR}/signal.10M.dat)
|
||||
add_test(phich_file_test phich_file_test -c 150 -n 50 -p 2 -i ${CMAKE_CURRENT_SOURCE_DIR}/signal.10M.dat)
|
||||
add_test(pdcch_file_test pdcch_file_test -c 1 -f 3 -n 6 -p 1 -i ${CMAKE_CURRENT_SOURCE_DIR}/signal.1.92M.amar.dat)
|
||||
add_test(pdsch_pdcch_file_test pdsch_pdcch_file_test -c 1 -f 3 -n 6 -p 1 -i ${CMAKE_CURRENT_SOURCE_DIR}/signal.1.92M.amar.dat)
|
||||
add_test(pdsch_pdcch_file_test pdsch_pdcch_file_test -c 1 -f 3 -n 6 -p 1 -i ${CMAKE_CURRENT_SOURCE_DIR}/signal.1.92M.amar.dat)
|
||||
add_test(pmch_file_test pmch_file_test -i ${CMAKE_CURRENT_SOURCE_DIR}/pmch_100prbs_MCS2_SR0.bin)
|
||||
|
||||
########################################################################
|
||||
# PUSCH TEST
|
||||
|
|
|
@ -131,7 +131,11 @@ int base_init() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (srslte_chest_dl_init(&chest, cell)) {
|
||||
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
return -1;
|
||||
}
|
||||
if (srslte_chest_dl_set_cell(&chest, cell)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -141,7 +145,11 @@ int base_init() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (srslte_pbch_init(&pbch, cell)) {
|
||||
if (srslte_pbch_init(&pbch)) {
|
||||
fprintf(stderr, "Error initiating PBCH\n");
|
||||
return -1;
|
||||
}
|
||||
if (srslte_pbch_set_cell(&pbch, cell)) {
|
||||
fprintf(stderr, "Error initiating PBCH\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue