add tdd/ca support

master
Ismael Gomez 6 years ago committed by Andre Puschmann
parent 963a5faad0
commit 7780b1aba5

@ -18,7 +18,7 @@ AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true #Changed
BinPackArguments: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: true #Changed
@ -90,6 +90,10 @@ PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left #Changed
RawStringFormats:
- Delimiter: pb
Language: TextProto
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true

@ -51,8 +51,7 @@ find_package(SRSGUI)
if(SRSGUI_FOUND)
include_directories(${SRSGUI_INCLUDE_DIRS})
target_link_libraries(pdsch_ue ${SRSGUI_LIBRARIES})
else(SRSGUI_FOUND)
add_definitions(-DDISABLE_GRAPHICS)
add_definitions(-DENABLE_GUI)
endif(SRSGUI_FOUND)
@ -65,9 +64,6 @@ if(RF_FOUND)
add_executable(cell_search cell_search.c)
target_link_libraries(cell_search srslte_phy srslte_common srslte_rf)
add_executable(cell_measurement cell_measurement.c)
target_link_libraries(cell_measurement srslte_phy srslte_common srslte_rf)
add_executable(usrp_capture usrp_capture.c)
target_link_libraries(usrp_capture srslte_phy srslte_rf)

@ -1,421 +0,0 @@
/**
*
* \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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#define ENABLE_AGC_DEFAULT
#include "srslte/srslte.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/phy/rf/rf_utils.h"
#include "srslte/common/crash_handler.h"
cell_search_cfg_t cell_detect_config = {
SRSLTE_DEFAULT_MAX_FRAMES_PBCH,
SRSLTE_DEFAULT_MAX_FRAMES_PSS,
SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES,
0
};
/**********************************************************************
* Program arguments processing
***********************************************************************/
typedef struct {
int nof_subframes;
bool disable_plots;
int force_N_id_2;
char *rf_args;
float rf_freq;
float rf_gain;
}prog_args_t;
void args_default(prog_args_t *args) {
args->nof_subframes = -1;
args->force_N_id_2 = -1; // Pick the best
args->rf_args = "";
args->rf_freq = -1.0;
#ifdef ENABLE_AGC_DEFAULT
args->rf_gain = -1;
#else
args->rf_gain = 50;
#endif
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [aglnv] -f rx_frequency (in Hz)\n", prog);
printf("\t-a RF args [Default %s]\n", args->rf_args);
printf("\t-g RF RX gain [Default %.2f dB]\n", args->rf_gain);
printf("\t-l Force N_id_2 [Default best]\n");
printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes);
printf("\t-v [set srslte_verbose to debug, default none]\n");
}
int parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "aglnvf")) != -1) {
switch (opt) {
case 'a':
args->rf_args = argv[optind];
break;
case 'g':
args->rf_gain = atof(argv[optind]);
break;
case 'f':
args->rf_freq = atof(argv[optind]);
break;
case 'n':
args->nof_subframes = atoi(argv[optind]);
break;
case 'l':
args->force_N_id_2 = atoi(argv[optind]);
break;
case 'v':
srslte_verbose++;
break;
default:
usage(args, argv[0]);
return -1;
}
}
if (args->rf_freq < 0) {
usage(args, argv[0]);
return -1;
}
return 0;
}
/**********************************************************************/
/* TODO: Do something with the output data */
uint8_t *data[SRSLTE_MAX_CODEWORDS];
bool go_exit = false;
void sig_int_handler(int signo)
{
printf("SIGINT received. Exiting...\n");
if (signo == SIGINT) {
go_exit = true;
}
}
int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *q) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return srslte_rf_recv(h, data[0], nsamples, 1);
}
enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state;
#define MAX_SINFO 10
#define MAX_NEIGHBOUR_CELLS 128
int main(int argc, char **argv) {
int ret;
cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL, NULL};
prog_args_t prog_args;
srslte_cell_t cell;
int64_t sf_cnt;
srslte_ue_sync_t ue_sync;
srslte_ue_mib_t ue_mib;
srslte_rf_t rf;
srslte_ue_dl_t ue_dl;
srslte_ofdm_t fft;
srslte_chest_dl_t chest;
uint32_t nframes=0;
uint32_t nof_trials = 0;
uint32_t sfn = 0; // system frame number
int n;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
int sfn_offset;
float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0;
cf_t *ce[SRSLTE_MAX_PORTS];
float cfo = 0;
bool acks[SRSLTE_MAX_CODEWORDS] = {false};
srslte_debug_handle_crash(argc, argv);
if (parse_args(&prog_args, argc, argv)) {
exit(-1);
}
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, prog_args.rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
if (prog_args.rf_gain > 0) {
srslte_rf_set_rx_gain(&rf, prog_args.rf_gain);
} else {
printf("Starting AGC thread...\n");
if (srslte_rf_start_gain_thread(&rf, false)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
srslte_rf_set_rx_gain(&rf, 50);
}
sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
data[i] = srslte_vec_malloc(sizeof(uint8_t) * 1500*8);
}
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
signal(SIGINT, sig_int_handler);
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
/* set receiver frequency */
srslte_rf_set_rx_freq(&rf, (double) prog_args.rf_freq);
srslte_rf_rx_wait_lo_locked(&rf);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.rf_freq/1000000);
cell_detect_config.init_agc = (prog_args.rf_gain<0);
uint32_t ntrial=0;
do {
ret = rf_search_and_decode_mib(&rf, 1, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
exit(-1);
} else if (ret == 0 && !go_exit) {
printf("Cell not found after %d trials. Trying again (Press Ctrl+C to exit)\n", ntrial++);
}
} while (ret == 0 && !go_exit);
if (go_exit) {
exit(0);
}
/* set sampling frequency */
int srate = srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {
if (srate < 10e6) {
srslte_rf_set_master_clock_rate(&rf, 4*srate);
} else {
srslte_rf_set_master_clock_rate(&rf, srate);
}
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate);
if (srate_rf != srate) {
fprintf(stderr, "Could not set sampling rate\n");
exit(-1);
}
} else {
fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb);
exit(-1);
}
INFO("Stopping RF and flushing buffer...\n");
srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&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_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
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, sf_buffer, 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);
/* Initialize subframe counter */
sf_cnt = 0;
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
}
if (srslte_ofdm_rx_init(&fft, cell.cp, sf_buffer[0], sf_symbols, cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
return -1;
}
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;
}
srslte_rf_start_rx_stream(&rf, false);
float rx_gain_offset = 0;
/* Main loop */
while ((sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) && !go_exit) {
ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer);
if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
}
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) {
switch (state) {
case DECODE_MIB:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
srslte_pbch_decode_reset(&ue_mib.pbch);
n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
return -1;
} else if (n == SRSLTE_UE_MIB_FOUND) {
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
printf("Decoded MIB. SFN: %d, offset: %d\n", sfn, sfn_offset);
sfn = (sfn + sfn_offset)%1024;
state = DECODE_SIB;
}
}
break;
case DECODE_SIB:
/* We are looking for SI Blocks, search only in appropiate places */
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
n = srslte_ue_dl_decode(&ue_dl, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks);
if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
return -1;
} else if (n == 0) {
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,
(float) ue_dl.nof_detected/nof_trials);
nof_trials++;
} else {
printf("Decoded SIB1. Payload: ");
srslte_vec_fprint_byte(stdout, data[0], n/8);;
state = MEASURE;
}
}
break;
case MEASURE:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
/* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&fft);
srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync));
rssi = SRSLTE_VEC_EMA(srslte_vec_avg_power_cf(sf_buffer[0],SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb))),rssi,0.05);
rssi_utra = SRSLTE_VEC_EMA(srslte_chest_dl_get_rssi(&chest),rssi_utra,0.05);
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&chest),rsrq,0.05);
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&chest),rsrp,0.05);
snr = SRSLTE_VEC_EMA(srslte_chest_dl_get_snr(&chest),snr,0.05);
nframes++;
}
if ((nframes%100) == 0 || rx_gain_offset == 0) {
if (srslte_rf_has_rssi(&rf)) {
rx_gain_offset = 30+10*log10(rssi*1000)-srslte_rf_get_rssi(&rf);
} else {
rx_gain_offset = srslte_rf_get_rx_gain(&rf);
}
}
// Plot and Printf
if ((nframes%10) == 0) {
printf("CFO: %+8.4f kHz, SFO: %+8.4f Hz, RSSI: %5.1f dBm, RSSI/ref-symbol: %+5.1f dBm, "
"RSRP: %+5.1f dBm, RSRQ: %5.1f dB, SNR: %5.1f dB\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync),
10*log10(rssi*1000) - rx_gain_offset,
10*log10(rssi_utra*1000)- rx_gain_offset,
10*log10(rsrp*1000) - rx_gain_offset,
10*log10(rsrq), 10*log10(snr));
if (srslte_verbose != SRSLTE_VERBOSE_NONE) {
printf("\n");
}
}
break;
}
if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) {
sfn++;
if (sfn == 1024) {
sfn = 0;
}
}
} else if (ret == 0) {
printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r",
srslte_sync_get_peak_value(&ue_sync.sfind),
ue_sync.frame_total_cnt, ue_sync.state);
}
sf_cnt++;
} // Main loop
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data[i]) {
free(data[i]);
}
}
srslte_ue_sync_free(&ue_sync);
srslte_rf_close(&rf);
printf("\nBye\n");
exit(0);
}

@ -56,13 +56,11 @@
int band = -1;
int earfcn_start=-1, earfcn_end = -1;
cell_search_cfg_t cell_detect_config = {
SRSLTE_DEFAULT_MAX_FRAMES_PBCH,
SRSLTE_DEFAULT_MAX_FRAMES_PSS,
SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES,
0
};
cell_search_cfg_t cell_detect_config = {.max_frames_pbch = SRSLTE_DEFAULT_MAX_FRAMES_PBCH,
.max_frames_pss = SRSLTE_DEFAULT_MAX_FRAMES_PSS,
.nof_valid_pss_frames = SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES,
.init_agc = 0,
.force_tdd = false};
struct cells {
srslte_cell_t cell;
@ -121,13 +119,10 @@ void parse_args(int argc, char **argv) {
}
}
int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *t) {
int srslte_rf_recv_wrapper(void* h, void* data, uint32_t nsamples, srslte_timestamp_t* t)
{
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
void *ptr[SRSLTE_MAX_PORTS];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ptr[i] = data[i];
}
return srslte_rf_recv_with_time_multi((srslte_rf_t*) h, ptr, nsamples, 1, NULL, NULL);
return srslte_rf_recv_with_time((srslte_rf_t*)h, data, nsamples, 1, NULL, NULL);
}
bool go_exit = false;
@ -160,7 +155,7 @@ int main(int argc, char **argv) {
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
ERROR("Error opening rf\n");
exit(-1);
}
if (!cell_detect_config.init_agc) {
@ -168,7 +163,7 @@ int main(int argc, char **argv) {
} else {
printf("Starting AGC thread...\n");
if (srslte_rf_start_gain_thread(&rf, false)) {
fprintf(stderr, "Error opening rf\n");
ERROR("Error opening rf\n");
exit(-1);
}
srslte_rf_set_rx_gain(&rf, 50);
@ -181,7 +176,7 @@ int main(int argc, char **argv) {
nof_freqs = srslte_band_get_fd_band(band, channels, earfcn_start, earfcn_end, MAX_EARFCN);
if (nof_freqs < 0) {
fprintf(stderr, "Error getting EARFCN list\n");
ERROR("Error getting EARFCN list\n");
exit(-1);
}
@ -191,8 +186,8 @@ 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");
if (srslte_ue_cellsearch_init(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, (void*)&rf)) {
ERROR("Error initiating UE cell detect\n");
exit(-1);
}
@ -211,12 +206,13 @@ int main(int argc, char **argv) {
for (freq=0;freq<nof_freqs && !go_exit;freq++) {
/* set rf_freq */
srslte_rf_set_rx_freq(&rf, (double) channels[freq].fd * MHZ);
srslte_rf_set_rx_freq(&rf, 0, (double)channels[freq].fd * MHZ);
srslte_rf_rx_wait_lo_locked(&rf);
INFO("Set rf_freq to %.3f MHz\n", (double) channels[freq].fd * MHZ/1000000);
printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz looking for PSS.\n", freq, nof_freqs,
channels[freq].id, channels[freq].fd);fflush(stdout);
printf(
"[%3d/%d]: EARFCN %d Freq. %.2f MHz looking for PSS.\n", freq, nof_freqs, channels[freq].id, channels[freq].fd);
fflush(stdout);
if (SRSLTE_VERBOSE_ISINFO()) {
printf("\n");
@ -231,7 +227,7 @@ int main(int argc, char **argv) {
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
if (n < 0) {
fprintf(stderr, "Error searching cell\n");
ERROR("Error searching cell\n");
exit(-1);
} else if (n > 0) {
for (int i=0;i<3;i++) {
@ -241,16 +237,13 @@ int main(int argc, char **argv) {
cell.cp = found_cells[i].cp;
int ret = rf_mib_decoder(&rf, 1, &cell_detect_config, &cell, NULL);
if (ret < 0) {
fprintf(stderr, "Error decoding MIB\n");
ERROR("Error decoding MIB\n");
exit(-1);
}
if (ret == SRSLTE_UE_MIB_FOUND) {
printf("Found CELL ID %d. %d PRB, %d ports\n",
cell.id,
cell.nof_prb,
cell.nof_ports);
printf("Found CELL ID %d. %d PRB, %d ports\n", cell.id, cell.nof_prb, cell.nof_ports);
if (cell.nof_ports > 0) {
memcpy(&results[n_found_cells].cell, &cell, sizeof(srslte_cell_t));
results[n_found_cells].cell = cell;
results[n_found_cells].freq = channels[freq].fd;
results[n_found_cells].dl_earfcn = channels[freq].id;
results[n_found_cells].power = found_cells[i].peak;

@ -34,8 +34,6 @@
#include <semaphore.h>
#include <signal.h>
#include "srslte/common/crash_handler.h"
#include <srslte/phy/common/phy_common.h>
#include <srslte/phy/phch/pdsch_cfg.h>
#include "srslte/common/gen_mch_tables.h"
#include "srslte/srslte.h"
@ -64,7 +62,9 @@ srslte_cell_t cell = {
0, // cell_id
SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_NORM, // PHICH length
SRSLTE_PHICH_R_1 // PHICH resources
SRSLTE_PHICH_R_1, // PHICH resources
SRSLTE_FDD,
};
uint16_t c = -1;
@ -75,8 +75,7 @@ uint32_t cfi = 2;
uint32_t mcs_idx = 1, last_mcs_idx = 1;
int nof_frames = -1;
char mimo_type_str[32] = "single";
srslte_tm_t transmission_mode = SRSLTE_TM1;
uint32_t nof_tb = 1;
uint32_t multiplex_pmi = 0;
uint32_t multiplex_nof_layers = 1;
@ -98,10 +97,10 @@ srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_pmch_t pmch;
srslte_pdsch_cfg_t pmch_cfg;
srslte_pmch_cfg_t pmch_cfg;
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
srslte_regs_t regs;
srslte_ra_dl_dci_t ra_dl;
srslte_dci_dl_t dci_dl;
int rvidx[SRSLTE_MAX_CODEWORDS] = {0, 0};
cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL}, *output_buffer [SRSLTE_MAX_PORTS] = {NULL};
@ -145,7 +144,7 @@ void usage(char *prog) {
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-x Transmission mode [1-4] [Default %d]\n", transmission_mode + 1);
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);
printf("\t-u listen TCP/UDP port for input data (if mbsfn is active then the stream is over mbsfn only) (-1 is random) [Default %d]\n", net_port);
@ -194,8 +193,7 @@ void parse_args(int argc, char **argv) {
cell.id = atoi(argv[optind]);
break;
case 'x':
strncpy(mimo_type_str, argv[optind], 31);
mimo_type_str[31] = 0;
transmission_mode = (srslte_tm_t)(atoi(argv[optind]) - 1);
break;
case 'b':
multiplex_pmi = (uint32_t) atoi(argv[optind]);
@ -231,28 +229,18 @@ void parse_args(int argc, char **argv) {
void base_init() {
int i;
/* Select transmission mode */
if (srslte_str2mimotype(mimo_type_str, &pdsch_cfg.mimo_type)) {
ERROR("Wrong transmission mode! Allowed modes: single, diversity, cdd and multiplex");
exit(-1);
}
/* Configure cell and PDSCH in function of the transmission mode */
switch(pdsch_cfg.mimo_type) {
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
switch (transmission_mode) {
case SRSLTE_TM1:
cell.nof_ports = 1;
break;
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
cell.nof_ports = 2;
break;
case SRSLTE_MIMO_TYPE_CDD:
cell.nof_ports = 2;
break;
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
case SRSLTE_TM2:
case SRSLTE_TM3:
case SRSLTE_TM4:
cell.nof_ports = 2;
break;
default:
ERROR("Transmission mode not implemented.");
ERROR("Transmission mode %d not implemented or invalid\n", transmission_mode);
exit(-1);
}
@ -291,7 +279,7 @@ void base_init() {
if (output_file_name) {
if (strcmp(output_file_name, "NULL")) {
if (srslte_filesink_init(&fsink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
fprintf(stderr, "Error opening file %s\n", output_file_name);
ERROR("Error opening file %s\n", output_file_name);
exit(-1);
}
null_file_sink = false;
@ -313,12 +301,12 @@ void base_init() {
if (net_port > 0) {
if (srslte_netsource_init(&net_source, "127.0.0.1", net_port, SRSLTE_NETSOURCE_UDP)) {
fprintf(stderr, "Error creating input UDP socket at port %d\n", net_port);
ERROR("Error creating input UDP socket at port %d\n", net_port);
exit(-1);
}
if (null_file_sink) {
if (srslte_netsink_init(&net_sink, "127.0.0.1", net_port+1, SRSLTE_NETSINK_TCP)) {
fprintf(stderr, "Error sink\n");
ERROR("Error sink\n");
exit(-1);
}
}
@ -331,7 +319,7 @@ void base_init() {
/* create ifft object */
for (i = 0; i < cell.nof_ports; i++) {
if (srslte_ofdm_tx_init(&ifft[i], SRSLTE_CP_NORM, sf_buffer[i], output_buffer[i], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
ERROR("Error creating iFFT object\n");
exit(-1);
}
@ -339,18 +327,18 @@ void base_init() {
}
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, sf_buffer[0], output_buffer[0], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
ERROR("Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, 2);
srslte_ofdm_set_normalize(&ifft_mbsfn, true);
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
ERROR("Error creating PBCH object\n");
exit(-1);
}
if (srslte_pbch_set_cell(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
ERROR("Error creating PBCH object\n");
exit(-1);
}
@ -358,33 +346,33 @@ void base_init() {
if (srslte_regs_init(&regs, cell)) {
fprintf(stderr, "Error initiating regs\n");
ERROR("Error initiating regs\n");
exit(-1);
}
if (srslte_pcfich_init(&pcfich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
ERROR("Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
ERROR("Error creating PBCH object\n");
exit(-1);
}
if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDCCH object\n");
ERROR("Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch, &regs, cell)) {
fprintf(stderr, "Error creating PDCCH object\n");
ERROR("Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdsch_init_enb(&pdsch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
ERROR("Error creating PDSCH object\n");
exit(-1);
}
if (srslte_pdsch_set_cell(&pdsch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
ERROR("Error creating PDSCH object\n");
exit(-1);
}
@ -392,8 +380,8 @@ void base_init() {
if(mbsfn_area_id > -1){
if (srslte_pmch_init(&pmch, cell.nof_prb)) {
fprintf(stderr, "Error creating PMCH object\n");
if (srslte_pmch_init(&pmch, cell.nof_prb, 1)) {
ERROR("Error creating PMCH object\n");
}
srslte_pmch_set_area_id(&pmch, mbsfn_area_id);
}
@ -401,12 +389,12 @@ void base_init() {
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
softbuffers[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1);
if (!softbuffers[i]) {
fprintf(stderr, "Error allocating soft buffer\n");
ERROR("Error allocating soft buffer\n");
exit(-1);
}
if (srslte_softbuffer_tx_init(softbuffers[i], cell.nof_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
ERROR("Error initiating soft buffer\n");
exit(-1);
}
}
@ -500,53 +488,53 @@ uint32_t prbset_to_bitmask() {
int update_radl() {
ZERO_OBJECT(dci_dl);
/* Configure cell and PDSCH in function of the transmission mode */
switch(pdsch_cfg.mimo_type) {
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
pdsch_cfg.nof_layers = 1;
switch (transmission_mode) {
case SRSLTE_TM1:
case SRSLTE_TM2:
nof_tb = 1;
dci_dl.format = SRSLTE_DCI_FORMAT1;
break;
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
pdsch_cfg.nof_layers = 2;
nof_tb = 1;
break;
case SRSLTE_MIMO_TYPE_CDD:
pdsch_cfg.nof_layers = 2;
case SRSLTE_TM3:
dci_dl.format = SRSLTE_DCI_FORMAT2A;
nof_tb = 2;
break;
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
pdsch_cfg.nof_layers = multiplex_nof_layers;
case SRSLTE_TM4:
dci_dl.format = SRSLTE_DCI_FORMAT2;
nof_tb = multiplex_nof_layers;
if (multiplex_nof_layers == 1) {
dci_dl.pinfo = (uint8_t)(multiplex_pmi + 1);
} else {
dci_dl.pinfo = (uint8_t)multiplex_pmi;
}
break;
default:
ERROR("Transmission mode not implemented.");
exit(-1);
}
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
ra_dl.harq_process = 0;
ra_dl.mcs_idx = mcs_idx;
ra_dl.ndi = 0;
ra_dl.rv_idx = rvidx[0];
ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask();
ra_dl.tb_en[0] = 1;
dci_dl.rnti = UE_CRNTI;
dci_dl.pid = 0;
dci_dl.tb[0].mcs_idx = mcs_idx;
dci_dl.tb[0].ndi = 0;
dci_dl.tb[0].rv = rvidx[0];
dci_dl.tb[0].cw_idx = 0;
dci_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
dci_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask();
if (nof_tb > 1) {
ra_dl.mcs_idx_1 = mcs_idx;
ra_dl.ndi_1 = 0;
ra_dl.rv_idx_1 = rvidx[1];
ra_dl.tb_en[1] = 1;
}
srslte_ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
srslte_ra_dl_grant_t dummy_grant;
srslte_ra_nbits_t dummy_nbits[SRSLTE_MAX_CODEWORDS];
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) {
dci_dl.tb[1].mcs_idx = mcs_idx;
dci_dl.tb[1].ndi = 0;
dci_dl.tb[1].rv = rvidx[1];
dci_dl.tb[1].cw_idx = 1;
} else {
SRSLTE_DCI_TB_DISABLE(dci_dl.tb[1]);
}
srslte_dci_dl_fprint(stdout, &dci_dl, cell.nof_prb);
if (transmission_mode != SRSLTE_TM1) {
printf("\nTransmission mode key table:\n");
printf(" Mode | 1TB | 2TB |\n");
printf("----------+---------+-----+\n");
@ -602,40 +590,40 @@ int update_control() {
} else {
switch (input[0]) {
case 'q':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
transmission_mode = SRSLTE_TM4;
multiplex_pmi = 0;
multiplex_nof_layers = 1;
break;
case 'w':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
transmission_mode = SRSLTE_TM4;
multiplex_pmi = 1;
multiplex_nof_layers = 1;
break;
case 'e':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
transmission_mode = SRSLTE_TM4;
multiplex_pmi = 2;
multiplex_nof_layers = 1;
break;
case 'r':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
transmission_mode = SRSLTE_TM4;
multiplex_pmi = 3;
multiplex_nof_layers = 1;
break;
case 'a':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
transmission_mode = SRSLTE_TM4;
multiplex_pmi = 0;
multiplex_nof_layers = 2;
break;
case 's':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
transmission_mode = SRSLTE_TM4;
multiplex_pmi = 1;
multiplex_nof_layers = 2;
break;
case 'z':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_CDD;
transmission_mode = SRSLTE_TM3;
break;
case 'x':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
transmission_mode = SRSLTE_TM2;
break;
default:
last_mcs_idx = mcs_idx;
@ -671,7 +659,10 @@ void *net_thread_fnc(void *arg) {
if (n > 0) {
// FIXME: I assume that both transport blocks have same size in case of 2 tb are active
int nbytes = 1 + (((mbsfn_area_id > -1)?(pmch_cfg.grant.mcs[0].tbs):(pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs)) - 1) / 8;
int nbytes = 1 + (((mbsfn_area_id > -1) ? (pmch_cfg.pdsch_cfg.grant.tb[0].tbs)
: (pdsch_cfg.grant.tb[0].tbs + pdsch_cfg.grant.tb[1].tbs)) -
1) /
8;
rpm += n;
INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes);
wpm = 0;
@ -697,7 +688,7 @@ void *net_thread_fnc(void *arg) {
} else if (n == 0) {
rpm = 0;
} else {
fprintf(stderr, "Error receiving from network\n");
ERROR("Error receiving from network\n");
exit(-1);
}
} while(n >= 0);
@ -713,9 +704,8 @@ int main(int argc, char **argv) {
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
int i;
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
cf_t *slot1_symbols[SRSLTE_MAX_PORTS];
srslte_dci_msg_t dci_msg;
srslte_dci_location_t locations[SRSLTE_NSUBFRAMES_X_FRAME][30];
srslte_dci_location_t locations[SRSLTE_NOF_SF_X_FRAME][30];
uint32_t sfn;
srslte_refsignal_t csr_refs;
srslte_refsignal_t mbsfn_refs;
@ -754,33 +744,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 reference signals */
if(srslte_refsignal_cs_init(&csr_refs, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
ERROR("Error initializing equalizer\n");
exit(-1);
}
if (mbsfn_area_id > -1) {
if(srslte_refsignal_mbsfn_init(&mbsfn_refs, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
ERROR("Error initializing equalizer\n");
exit(-1);
}
if (srslte_refsignal_mbsfn_set_cell(&mbsfn_refs, cell, mbsfn_area_id)) {
fprintf(stderr, "Error initializing MBSFNR signal\n");
ERROR("Error initializing MBSFNR signal\n");
exit(-1);
}
}
if(srslte_refsignal_cs_set_cell(&csr_refs, cell)){
fprintf(stderr, "Error setting cell\n");
ERROR("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)];
}
@ -805,16 +793,15 @@ int main(int argc, char **argv) {
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
float srate_rf = srslte_rf_set_tx_srate(&rf, (double)srate);
if (srate_rf != srate) {
fprintf(stderr, "Could not set sampling rate\n");
ERROR("Could not set sampling rate\n");
exit(-1);
}
} else {
fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb);
ERROR("Invalid number of PRB %d\n", cell.nof_prb);
exit(-1);
}
printf("Set TX gain: %.1f dB\n", srslte_rf_set_tx_gain(&rf, rf_gain));
printf("Set TX freq: %.2f MHz\n",
srslte_rf_set_tx_freq(&rf, rf_freq) / 1000000);
printf("Set TX freq: %.2f MHz\n", srslte_rf_set_tx_freq(&rf, cell.nof_ports, rf_freq) / 1000000);
}
#endif
@ -828,10 +815,16 @@ int main(int argc, char **argv) {
exit(-1);
}
}
pmch_cfg.grant.mcs[0].tbs = 1096;
pmch_cfg.pdsch_cfg.grant.tb[0].tbs = 1096;
srslte_dl_sf_cfg_t dl_sf;
ZERO_OBJECT(dl_sf);
/* 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);
for (i = 0; i < SRSLTE_NOF_SF_X_FRAME; i++) {
dl_sf.cfi = cfi;
dl_sf.tti = i;
srslte_pdcch_ue_locations(&pdcch, &dl_sf, locations[i], 30, UE_CRNTI);
}
nf = 0;
@ -846,8 +839,16 @@ int main(int argc, char **argv) {
bool start_of_burst = true;
#endif
ZERO_OBJECT(pdsch_cfg);
for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
pdsch_cfg.softbuffers.tx[i] = softbuffers[i];
}
pdsch_cfg.rnti = UE_CRNTI;
pmch_cfg.pdsch_cfg = pdsch_cfg;
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++) {
for (sf_idx = 0; sf_idx < SRSLTE_NOF_SF_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);
@ -866,21 +867,25 @@ int main(int argc, char **argv) {
if (mch_table[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 {
dl_sf.tti = nf * 10 + sf_idx;
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_refsignal_cs_put_sf(&csr_refs, &dl_sf, (uint32_t)i, 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_pbch_encode(&pbch, bch_payload, sf_symbols, nf % 4);
}
srslte_pcfich_encode(&pcfich, cfi, sf_symbols, sf_idx);
dl_sf.tti = nf * 10 + sf_idx;
dl_sf.cfi = cfi;
srslte_pcfich_encode(&pcfich, &dl_sf, sf_symbols);
/* Update DL resource allocation from control port */
if (update_control(sf_idx)) {
fprintf(stderr, "Error updating parameters from control port\n");
ERROR("Error updating parameters from control port\n");
}
/* Transmit PDCCH + PDSCH only when there is data to send */
@ -890,10 +895,10 @@ int main(int argc, char **argv) {
INFO("Transmitting packet from port\n");
}
} else {
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs);
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.tb[0].tbs + pdsch_cfg.grant.tb[1].tbs);
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++) {
if (pdsch_cfg.grant.tb[tb].enabled) {
for (i = 0; i < pdsch_cfg.grant.tb[tb].tbs / 8; i++) {
data[tb][i] = (uint8_t) rand();
}
}
@ -907,54 +912,35 @@ int main(int argc, char **argv) {
}
if (send_data) {
if (mch_table[sf_idx] == 0 || 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);
}
dl_sf.sf_type = SRSLTE_SF_NORM;
/* 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");
dci_msg.location = locations[sf_idx][0];
srslte_dci_msg_pack_pdsch(&cell, &dl_sf, NULL, &dci_dl, &dci_msg);
if (srslte_pdcch_encode(&pdcch, &dl_sf, &dci_msg, sf_symbols)) {
ERROR("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");
if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, transmission_mode, &dci_dl, &pdsch_cfg.grant)) {
ERROR("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");
if (srslte_pdsch_encode(&pdsch, &dl_sf, &pdsch_cfg, data, sf_symbols)) {
ERROR("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");
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.tb[tb].tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.tb[tb].tbs - 1) / 8) < 0) {
ERROR("Error sending data through UDP socket\n");
}
}
}
@ -964,48 +950,37 @@ int main(int argc, char **argv) {
}
}
}else{ // We're sending MCH on subframe 1 - PDCCH + PMCH
dl_sf.sf_type = SRSLTE_SF_MBSFN;
/* 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.tb_en[0] = true;
grant.tb_en[1] = false;
grant.mcs[0].idx = 2;
grant.nof_prb = cell.nof_prb;
grant.sf_type = SRSLTE_SF_MBSFN;
srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb);
grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod);
for(int i = 0; i < 2; i++){
for(int j = 0; j < grant.nof_prb; j++){
grant.prb_idx[i][j] = true;
}
}
for(int i = 0; i < grant.mcs[0].tbs/8;i++)
{
data_mbms[i] = i%255;
}
/* Force 1 word and MCS 2 */
dci_dl.rnti = SRSLTE_MRNTI;
dci_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
dci_dl.type0_alloc.rbg_bitmask = 0xffffffff;
dci_dl.tb[0].mcs_idx = 2;
dci_dl.format = SRSLTE_DCI_FORMAT1;
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, sf_idx)) {
fprintf(stderr, "Error configuring PMCH\n");
/* Configure pdsch_cfg parameters */
if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, SRSLTE_TM1, &dci_dl, &pmch_cfg.pdsch_cfg.grant)) {
ERROR("Error configuring PDSCH\n");
exit(-1);
}
for (int i = 0; i < pmch_cfg.pdsch_cfg.grant.tb[0].tbs / 8; i++) {
data_mbms[i] = i % 255;
}
pmch_cfg.area_id = mbsfn_area_id;
/* Encode PMCH */
if (srslte_pmch_encode(&pmch, &pmch_cfg, softbuffers[0], data_mbms, mbsfn_area_id, sf_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
if (srslte_pmch_encode(&pmch, &dl_sf, &pmch_cfg, data_mbms, sf_symbols)) {
ERROR("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");
srslte_bit_pack_vector(data[0], data_tmp, pmch_cfg.pdsch_cfg.grant.tb[0].tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pmch_cfg.pdsch_cfg.grant.tb[0].tbs - 1) / 8) < 0) {
ERROR("Error sending data through UDP socket\n");
}
}
net_packet_ready = false;

@ -36,24 +36,24 @@
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include "srslte/common/gen_mch_tables.h"
#include "srslte/common/crash_handler.h"
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/io/filesink.h"
#include "srslte/srslte.h"
#define ENABLE_AGC_DEFAULT
#ifndef DISABLE_RF
#include "srslte/phy/rf/rf.h"
#include "srslte/phy/rf/rf_utils.h"
cell_search_cfg_t cell_detect_config = {
SRSLTE_DEFAULT_MAX_FRAMES_PBCH,
SRSLTE_DEFAULT_MAX_FRAMES_PSS,
SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES,
0
};
cell_search_cfg_t cell_detect_config = {.max_frames_pbch = SRSLTE_DEFAULT_MAX_FRAMES_PBCH,
.max_frames_pss = SRSLTE_DEFAULT_MAX_FRAMES_PSS,
.nof_valid_pss_frames = SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES,
.init_agc = 0,
.force_tdd = false};
#else
#warning Compiling pdsch_ue with no RF support
@ -61,17 +61,20 @@ cell_search_cfg_t cell_detect_config = {
//#define STDOUT_COMPACT
#ifndef DISABLE_GRAPHICS
#ifdef ENABLE_GUI
#include "srsgui/srsgui.h"
void init_plots();
pthread_t plot_thread;
sem_t plot_sem;
uint32_t plot_sf_idx = 0;
bool plot_track = true;
bool enable_mbsfn_plot = false;
#endif
#endif /* ENABLE_GUI */
char* output_file_name;
#define PRINT_CHANGE_SCHEDULIGN
//#define PRINT_CHANGE_SCHEDULING
//#define CORRECT_SAMPLE_OFFSET
@ -108,15 +111,20 @@ typedef struct {
int32_t mbsfn_area_id;
uint8_t non_mbsfn_region;
uint8_t mbsfn_sf_mask;
int tdd_special_sf;
int sf_config;
int verbose;
}prog_args_t;
void args_default(prog_args_t *args) {
void args_default(prog_args_t* args)
{
args->disable_plots = false;
args->disable_plots_except_constellation = false;
args->nof_subframes = -1;
args->rnti = SRSLTE_SIRNTI;
args->force_N_id_2 = -1; // Pick the best
args->tdd_special_sf = -1;
args->sf_config = -1;
args->input_file_name = NULL;
args->disable_cfo = false;
args->time_offset = 0;
@ -148,7 +156,7 @@ void args_default(prog_args_t *args) {
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [adgpPoOcildFRDnruMNv] -f rx_frequency (in Hz) | -i input_file\n", prog);
printf("Usage: %s [adgpPoOcildFRDnruMNvTG] -f rx_frequency (in Hz) | -i input_file\n", prog);
#ifndef DISABLE_RF
printf("\t-I RF dev [Default %s]\n", args->rf_dev);
printf("\t-a RF args [Default %s]\n", args->rf_args);
@ -173,12 +181,14 @@ void usage(prog_args_t *args, char *prog) {
printf("\t-F Enable RS-based CFO correction [Default %s]\n", !args->enable_cfo_ref ? "Disabled" : "Enabled");
printf("\t-R Average channel estimates on 1 ms [Default %s]\n", !args->average_subframe ? "Disabled" : "Enabled");
printf("\t-t Add time offset [Default %d]\n", args->time_offset);
#ifndef DISABLE_GRAPHICS
printf("\t-T Set TDD special subframe configuration [Default %d]\n", args->tdd_special_sf);
printf("\t-G Set TDD uplink/downlink configuration [Default %d]\n", args->sf_config);
#ifdef ENABLE_GUI
printf("\t-d disable plots [Default enabled]\n");
printf("\t-D disable all but constellation plots [Default enabled]\n");
#else
#else /* ENABLE_GUI */
printf("\t plots are disabled. Graphics library not available\n");
#endif
#endif /* ENABLE_GUI */
printf("\t-y set the cpu affinity mask [Default %d] \n ", args->cpu_affinity);
printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes);
printf("\t-s remote UDP port to send input signal (-1 does nothing with it) [Default %d]\n", args->net_port_signal);
@ -193,7 +203,8 @@ void usage(prog_args_t *args, char *prog) {
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "adAogliIpPcOCtdDFRnvrfuUsSZyWMNB")) != -1) {
while ((opt = getopt(argc, argv, "adAogliIpPcOCtdDFRnvrfuUsSZyWMNBTG")) != -1) {
switch (opt) {
case 'i':
args->input_file_name = argv[optind];
@ -240,6 +251,12 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
case 'f':
args->rf_freq = strtod(argv[optind], NULL);
break;
case 'T':
args->tdd_special_sf = atoi(argv[optind]);
break;
case 'G':
args->sf_config = atoi(argv[optind]);
break;
case 'n':
args->nof_subframes = atoi(argv[optind]);
break;
@ -299,12 +316,13 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
exit(-1);
}
}
/**********************************************************************/
/* TODO: Do something with the output data */
uint8_t *data[SRSLTE_MAX_CODEWORDS];
bool go_exit = false;
void sig_int_handler(int signo)
{
printf("SIGINT received. Exiting...\n");
@ -319,7 +337,9 @@ 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) {
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);
void* ptr[SRSLTE_MAX_PORTS];
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
@ -338,43 +358,44 @@ extern float mean_exec_time;
enum receiver_state { DECODE_MIB, DECODE_PDSCH } state;
srslte_cell_t cell;
srslte_ue_dl_t ue_dl;
srslte_ue_dl_cfg_t ue_dl_cfg;
srslte_dl_sf_cfg_t dl_sf;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_ue_sync_t ue_sync;
prog_args_t prog_args;
uint32_t sfn = 0; // system frame number
uint32_t pkt_errors = 0, pkt_total = 0, nof_detected = 0, pmch_pkt_errors = 0, pmch_pkt_total = 0, nof_trials = 0;
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_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
#define PRINT_LINE_ADVANCE_CURSOR() printf("\033[%dB", prev_nof_lines + 1)
int main(int argc, char **argv) {
struct timeval t[3];
int ret;
srslte_cell_t cell;
int64_t sf_cnt;
srslte_ue_mib_t ue_mib;
#ifndef DISABLE_RF
srslte_rf_t rf;
#endif
uint32_t nof_trials = 0;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
int sfn_offset;
float cfo = 0;
srslte_debug_handle_crash(argc, argv);
parse_args(&prog_args, argc, argv);
#ifndef DISABLE_GRAPHICS
#ifdef ENABLE_GUI
if (prog_args.mbsfn_area_id > -1) {
enable_mbsfn_plot = true;
}
#endif
#endif /* ENABLE_GUI */
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
data[i] = srslte_vec_malloc(sizeof(uint8_t) * 1500 * 8);
@ -383,6 +404,7 @@ int main(int argc, char **argv) {
go_exit = true;
}
}
uint8_t mch_table[10];
bzero(&mch_table[0], sizeof(uint8_t) * 10);
if (prog_args.mbsfn_area_id > -1) {
@ -400,7 +422,7 @@ int main(int argc, char **argv) {
CPU_SET((size_t)i, &cpuset);
}
if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset)) {
fprintf(stderr, "Error setting main thread affinity to %d \n", prog_args.cpu_affinity);
ERROR("Error setting main thread affinity to %d \n", prog_args.cpu_affinity);
exit(-1);
}
}
@ -408,20 +430,22 @@ int main(int argc, char **argv) {
if (prog_args.net_port > 0) {
if (srslte_netsink_init(&net_sink, prog_args.net_address, prog_args.net_port, SRSLTE_NETSINK_UDP)) {
fprintf(stderr, "Error initiating UDP socket to %s:%d\n", prog_args.net_address, prog_args.net_port);
ERROR("Error initiating UDP socket to %s:%d\n", prog_args.net_address, prog_args.net_port);
exit(-1);
}
srslte_netsink_set_nonblocking(&net_sink);
}
if (prog_args.net_port_signal > 0) {
if (srslte_netsink_init(&net_sink_signal, prog_args.net_address_signal,
prog_args.net_port_signal, SRSLTE_NETSINK_UDP)) {
fprintf(stderr, "Error initiating UDP socket to %s:%d\n", prog_args.net_address_signal, prog_args.net_port_signal);
if (srslte_netsink_init(
&net_sink_signal, prog_args.net_address_signal, prog_args.net_port_signal, SRSLTE_NETSINK_UDP)) {
ERROR("Error initiating UDP socket to %s:%d\n", prog_args.net_address_signal, prog_args.net_port_signal);
exit(-1);
}
srslte_netsink_set_nonblocking(&net_sink_signal);
}
float search_cell_cfo = 0;
#ifndef DISABLE_RF
if (!prog_args.input_file_name) {
@ -436,7 +460,7 @@ int main(int argc, char **argv) {
} else {
printf("Starting AGC thread...\n");
if (srslte_rf_start_gain_thread(&rf, false)) {
fprintf(stderr, "Error opening rf\n");
ERROR("Error opening rf\n");
exit(-1);
}
srslte_rf_set_rx_gain(&rf, srslte_rf_get_rx_gain(&rf));
@ -453,15 +477,15 @@ int main(int argc, char **argv) {
/* set receiver frequency */
printf("Tunning receiver to %.3f MHz\n", (prog_args.rf_freq + prog_args.file_offset_freq) / 1000000);
srslte_rf_set_rx_freq(&rf, prog_args.rf_freq + prog_args.file_offset_freq);
srslte_rf_set_rx_freq(&rf, prog_args.rf_nof_rx_ant, 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);
ret = rf_search_and_decode_mib(
&rf, prog_args.rf_nof_rx_ant, &cell_detect_config, prog_args.force_N_id_2, &cell, &search_cell_cfo);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
ERROR("Error searching for cell\n");
exit(-1);
} else if (ret == 0 && !go_exit) {
printf("Cell not found after %d trials. Trying again (Press Ctrl+C to exit)\n", ntrial++);
@ -484,11 +508,11 @@ int main(int argc, char **argv) {
printf("Setting sampling rate %.2f MHz\n", (float)srate / 1000000);
float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate);
if (srate_rf != srate) {
fprintf(stderr, "Could not set sampling rate\n");
ERROR("Could not set sampling rate\n");
exit(-1);
}
} else {
fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb);
ERROR("Invalid number of PRB %d\n", cell.nof_prb);
exit(-1);
}
@ -506,15 +530,19 @@ 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,
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");
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)) {
ERROR("Error initiating ue_sync\n");
exit(-1);
}
} else {
#ifndef DISABLE_RF
int decimate = 1;
int decimate = 0;
if (prog_args.decimate) {
if (prog_args.decimate > 4 || prog_args.decimate < 0) {
printf("Invalid decimation factor, setting to 1 \n");
@ -522,15 +550,18 @@ int main(int argc, char **argv) {
decimate = prog_args.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");
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)) {
ERROR("Error initiating ue_sync\n");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
ERROR("Error initiating ue_sync\n");
exit(-1);
}
#endif
@ -539,33 +570,61 @@ int main(int argc, char **argv) {
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));
}
srslte_ue_mib_t ue_mib;
if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
ERROR("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");
ERROR("Error initaiting UE MIB decoder\n");
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
ERROR("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");
ERROR("Error initiating UE downlink processing module\n");
exit(-1);
}
// Disable CP based CFO estimation during find
ue_sync.cfo_current_value = cfo/15000;
ue_sync.cfo_current_value = search_cell_cfo / 15000;
ue_sync.cfo_is_copied = true;
ue_sync.cfo_correct_enable_find = true;
srslte_sync_set_cfo_cp_enable(&ue_sync.sfind, false, 0);
ZERO_OBJECT(ue_dl_cfg);
ZERO_OBJECT(dl_sf);
ZERO_OBJECT(pdsch_cfg);
if (cell.frame_type == SRSLTE_TDD && prog_args.tdd_special_sf >= 0 && prog_args.sf_config >= 0) {
dl_sf.tdd_config.ss_config = prog_args.tdd_special_sf;
dl_sf.tdd_config.sf_config = prog_args.sf_config;
dl_sf.tdd_config.configured = true;
}
srslte_chest_dl_cfg_t chest_pdsch_cfg;
chest_pdsch_cfg.cfo_estimate_enable = prog_args.enable_cfo_ref;
chest_pdsch_cfg.cfo_estimate_sf_mask = 1023;
chest_pdsch_cfg.interpolate_subframe = !prog_args.average_subframe;
srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, prog_args.enable_cfo_ref, 1023);
srslte_chest_dl_average_subframe(&ue_dl.chest, prog_args.average_subframe);
// Special configuration for MBSFN channel estimation
srslte_chest_dl_cfg_t chest_mbsfn_cfg;
chest_mbsfn_cfg.filter_type = SRSLTE_CHEST_FILTER_TRIANGLE;
chest_mbsfn_cfg.filter_coef[0] = 0.1;
chest_mbsfn_cfg.interpolate_subframe = true;
chest_mbsfn_cfg.noise_alg = SRSLTE_NOISE_ALG_PSS;
// Allocate softbuffer buffers
srslte_softbuffer_rx_t rx_softbuffers[SRSLTE_MAX_CODEWORDS];
for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
pdsch_cfg.softbuffers.rx[i] = &rx_softbuffers[i];
srslte_softbuffer_rx_init(pdsch_cfg.softbuffers.rx[i], cell.nof_prb);
}
pdsch_cfg.rnti = prog_args.rnti;
/* 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);
@ -575,16 +634,13 @@ int main(int argc, char **argv) {
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;
#ifndef DISABLE_GRAPHICS
#ifdef ENABLE_GUI
if (!prog_args.disable_plots) {
init_plots(cell);
sleep(1);
}
#endif
#endif /* ENABLE_GUI */
#ifndef DISABLE_RF
if (!prog_args.input_file_name) {
@ -592,17 +648,6 @@ int main(int argc, char **argv) {
}
#endif
// Variables for measurements
uint32_t nframes=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, procrate = 0.0,
sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0;
bool decode_pdsch = false;
for (int i = 0; i < SRSLTE_MAX_LAYERS; i++) {
bzero(sinr[i], sizeof(float)*SRSLTE_MAX_CODEBOOKS);
}
#ifndef DISABLE_RF
if (prog_args.rf_gain < 0 && !prog_args.input_file_name) {
srslte_rf_info_t *rf_info = srslte_rf_get_info(&rf);
@ -613,9 +658,9 @@ int main(int argc, char **argv) {
cell_detect_config.init_agc);
}
#endif
#ifdef PRINT_CHANGE_SCHEDULIGN
srslte_ra_dl_dci_t old_dl_dci;
bzero(&old_dl_dci, sizeof(srslte_ra_dl_dci_t));
#ifdef PRINT_CHANGE_SCHEDULING
srslte_ra_dl_grant_t old_dl_dci;
bzero(&old_dl_dci, sizeof(srslte_ra_dl_grant_t));
#endif
ue_sync.cfo_correct_enable_track = !prog_args.disable_cfo;
@ -623,9 +668,22 @@ int main(int argc, char **argv) {
srslte_pbch_decode_reset(&ue_mib.pbch);
INFO("\nEntering main loop...\n\n");
// Variables for measurements
uint32_t nframes = 0;
float rsrp0 = 0.0, rsrp1 = 0.0, rsrq = 0.0, snr = 0.0, enodebrate = 0.0, uerate = 0.0, procrate = 0.0,
sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS];
bool decode_pdsch = false;
for (int i = 0; i < SRSLTE_MAX_LAYERS; i++) {
bzero(sinr[i], sizeof(float) * SRSLTE_MAX_CODEBOOKS);
}
/* Main loop */
uint64_t sf_cnt = 0;
uint32_t sfn = 0;
uint32_t last_decoded_tm = 0;
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
bool acks [SRSLTE_MAX_CODEWORDS] = {false};
char input[128];
PRINT_LINE_INIT();
@ -644,34 +702,44 @@ 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;
pkt_errors = 0;
pkt_total = 0;
nof_detected = 0;
nof_trials = 0;
}
}
ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer);
cf_t* buffers[SRSLTE_MAX_PORTS] = {};
for (int p = 0; p < SRSLTE_MAX_PORTS; p++) {
buffers[p] = sf_buffer[p];
}
ret = srslte_ue_sync_zerocopy(&ue_sync, buffers);
if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
ERROR("Error calling srslte_ue_sync_work()\n");
}
#ifdef CORRECT_SAMPLE_OFFSET
float sample_offset = (float) srslte_ue_sync_get_last_sample_offset(&ue_sync)+srslte_ue_sync_get_sfo(&ue_sync)/1000;
float sample_offset =
(float)srslte_ue_sync_get_last_sample_offset(&ue_sync) + srslte_ue_sync_get_sfo(&ue_sync) / 1000;
srslte_ue_dl_set_sample_offset(&ue_dl, sample_offset);
#endif
/* 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);
bool acks[SRSLTE_MAX_CODEWORDS] = {false};
struct timeval t[3];
uint32_t sf_idx = srslte_ue_sync_get_sfidx(&ue_sync);
switch (state) {
case DECODE_MIB:
if (sfidx == 0) {
if (sf_idx == 0) {
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
int sfn_offset;
n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
ERROR("Error decoding UE MIB\n");
exit(-1);
} else if (n == SRSLTE_UE_MIB_FOUND) {
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
@ -683,114 +751,127 @@ int main(int argc, char **argv) {
}
break;
case DECODE_PDSCH:
if (prog_args.rnti != SRSLTE_SIRNTI) {
decode_pdsch = true;
if (srslte_sfidx_tdd_type(dl_sf.tdd_config, sf_idx) == SRSLTE_TDD_SF_U) {
decode_pdsch = false;
}
} else {
/* We are looking for SIB1 Blocks, search only in appropiate places */
if ((sfidx == 5 && (sfn%2)==0) ||mch_table[sfidx] == 1) {
if ((sf_idx == 5 && (sfn % 2) == 0) || mch_table[sf_idx] == 1) {
decode_pdsch = true;
} else {
decode_pdsch = false;
}
}
uint32_t tti = sfn * 10 + sf_idx;
gettimeofday(&t[1], NULL);
if (decode_pdsch) {
if(mch_table[sfidx] == 0 || 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, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks);
srslte_sf_t sf_type;
if (mch_table[sf_idx] == 0 || prog_args.mbsfn_area_id < 0) { // Not an MBSFN subframe
sf_type = SRSLTE_SF_NORM;
// Set PDSCH channel estimation
ue_dl_cfg.chest_cfg = chest_pdsch_cfg;
} else {
/* Transmission mode 2 */
n = srslte_ue_dl_decode(&ue_dl, data, 1, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
acks);
sf_type = SRSLTE_SF_MBSFN;
if (n < 1) {
/* Transmission mode 3 */
n = srslte_ue_dl_decode(&ue_dl, data, 2, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
acks);
// Set MBSFN channel estimation
ue_dl_cfg.chest_cfg = chest_mbsfn_cfg;
}
if (n < 1) {
/* Transmission mode 4 */
n = srslte_ue_dl_decode(&ue_dl, data, 3, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync),
acks);
n = 0;
for (uint32_t tm = 0; tm < 4 && !n; tm++) {
dl_sf.tti = tti;
dl_sf.sf_type = sf_type;
ue_dl_cfg.cfg.tm = (srslte_tm_t)tm;
if ((ue_dl_cfg.cfg.tm == SRSLTE_TM1 && cell.nof_ports == 1) ||
(ue_dl_cfg.cfg.tm > SRSLTE_TM1 && cell.nof_ports > 1)) {
n = srslte_ue_dl_find_and_decode(&ue_dl, &dl_sf, &ue_dl_cfg, &pdsch_cfg, data, acks);
if (n > 0) {
nof_detected++;
last_decoded_tm = tm;
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (pdsch_cfg.grant.tb[tb].enabled) {
if (!acks[tb]) {
if (sf_type == SRSLTE_SF_NORM) {
pkt_errors++;
} else {
pmch_pkt_errors++;
}
}
if (sf_type == SRSLTE_SF_NORM) {
pkt_total++;
} else {
pmch_pkt_total++;
}
}
// Feed-back ue_sync with chest_dl CFO estimation
if (sfidx == 5 && prog_args.enable_cfo_ref) {
srslte_ue_sync_set_cfo_ref(&ue_sync, srslte_chest_dl_get_cfo(&ue_dl.chest));
}
}else{ // MBSFN subframe
n = srslte_ue_dl_decode_mbsfn(&ue_dl,
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);
}
}
// Feed-back ue_sync with chest_dl CFO estimation
if (sf_idx == 5 && prog_args.enable_cfo_ref) {
srslte_ue_sync_set_cfo_ref(&ue_sync, ue_dl.chest_res.cfo);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
if (n < 0) {
// fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) {
if (n > 0) {
/* Send data if socket active */
if (prog_args.net_port > 0) {
if(sfidx == 1) {
if (sf_idx == 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 < 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);
if (pdsch_cfg.grant.tb[tb].enabled) {
srslte_netsink_write(&net_sink, data[tb], 1 + (pdsch_cfg.grant.tb[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)) ||
memcmp(&ue_dl.dl_dci.type1_alloc, &old_dl_dci.type1_alloc, sizeof(srslte_ra_type1_t)) ||
memcmp(&ue_dl.dl_dci.type2_alloc, &old_dl_dci.type2_alloc, sizeof(srslte_ra_type2_t)))
{
memcpy(&old_dl_dci, &ue_dl.dl_dci, sizeof(srslte_ra_dl_dci_t));
#ifdef PRINT_CHANGE_SCHEDULING
if (pdsch_cfg.dci.cw[0].mcs_idx != old_dl_dci.cw[0].mcs_idx ||
memcmp(&pdsch_cfg.dci.type0_alloc, &old_dl_dci.type0_alloc, sizeof(srslte_ra_type0_t)) ||
memcmp(&pdsch_cfg.dci.type1_alloc, &old_dl_dci.type1_alloc, sizeof(srslte_ra_type1_t)) ||
memcmp(&pdsch_cfg.dci.type2_alloc, &old_dl_dci.type2_alloc, sizeof(srslte_ra_type2_t))) {
old_dl_dci = pdsch_cfg.dci;
fflush(stdout);
printf("Format: %s\n", srslte_dci_format_string(ue_dl.dci_format));
printf("DCI %s\n", srslte_dci_format_string(pdsch_cfg.dci.dci_format));
srslte_ra_pdsch_fprint(stdout, &old_dl_dci, cell.nof_prb);
srslte_ra_dl_grant_fprint(stdout, &ue_dl.pdsch_cfg.grant);
}
#endif
}
nof_trials++;
uint32_t nof_bits = ((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0));
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);
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05f);
enodebrate = SRSLTE_VEC_EMA(nof_bits/1000.0f, enodebrate, 0.05f);
uerate = SRSLTE_VEC_EMA(nof_bits/1000.0f, uerate, 0.001f);
uint32_t enb_bits = ((pdsch_cfg.grant.tb[0].enabled ? pdsch_cfg.grant.tb[0].tbs : 0) +
(pdsch_cfg.grant.tb[1].enabled ? pdsch_cfg.grant.tb[1].tbs : 0));
uint32_t ue_bits = ((acks[0] ? pdsch_cfg.grant.tb[0].tbs : 0) + (acks[1] ? pdsch_cfg.grant.tb[1].tbs : 0));
rsrq = SRSLTE_VEC_EMA(ue_dl.chest_res.rsrp_dbm, rsrq, 0.1f);
rsrp0 = SRSLTE_VEC_EMA(ue_dl.chest_res.rsrp_port_dbm[0], rsrp0, 0.05f);
rsrp1 = SRSLTE_VEC_EMA(ue_dl.chest_res.rsrp_port_dbm[1], rsrp1, 0.05f);
snr = SRSLTE_VEC_EMA(ue_dl.chest_res.snr_db, snr, 0.05f);
enodebrate = SRSLTE_VEC_EMA(enb_bits / 1000.0f, enodebrate, 0.05f);
uerate = SRSLTE_VEC_EMA(ue_bits / 1000.0f, uerate, 0.001f);
float elapsed = (float)t[0].tv_usec + t[0].tv_sec * 1.0e+6f;
if (elapsed != 0.0f) {
procrate = SRSLTE_VEC_EMA(nof_bits/elapsed, procrate, 0.01f);
procrate = SRSLTE_VEC_EMA(ue_bits / elapsed, procrate, 0.01f);
}
nframes++;
if (isnan(rsrq)) {
rsrq = 0;
}
if (isnan(noise)) {
noise = 0;
if (isnan(snr)) {
snr = 0;
}
if (isnan(rsrp0)) {
rsrp0 = 0;
@ -801,74 +882,45 @@ int main(int argc, char **argv) {
}
// Plot and Printf
if (sfidx == 5) {
if (sf_idx == 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),
ue_dl.pdsch_cfg.codebook_idx);
} else {
PRINT_LINE(" Tx scheme: %s", srslte_mimotype2str(ue_dl.pdsch_cfg.mimo_type));
}
/* Print basic Parameters */
PRINT_LINE(" nof layers: %d", ue_dl.pdsch_cfg.nof_layers);
PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant));
PRINT_LINE(" CFO: %+7.2f Hz", srslte_ue_sync_get_cfo(&ue_sync));
PRINT_LINE(" RSRP: %+5.1f dBm | %+5.1f dBm", 10 * log10(rsrp0)+30, 10 * log10(rsrp1)+30);
PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise));
PRINT_LINE(" Rb: %6.2f / %6.2f / %6.2f Mbps (net/maximum/processing)", uerate, enodebrate, procrate);
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.pdsch_pkt_errors / ue_dl.pdsch_pkts_total);
PRINT_LINE(" RSRP: %+5.1f dBm | %+5.1f dBm", rsrp0, rsrp1);
PRINT_LINE(" SNR: %+5.1f dB", snr);
PRINT_LINE(" TM: %d", last_decoded_tm + 1);
PRINT_LINE(
" Rb: %6.2f / %6.2f / %6.2f Mbps (net/maximum/processing)", uerate, enodebrate, procrate);
PRINT_LINE(" PDCCH-Miss: %5.2f%%", 100 * (1 - (float)nof_detected / nof_trials));
PRINT_LINE(" PDSCH-BLER: %5.2f%%", (float)100 * pkt_errors / pkt_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(" PMCH-BLER: %5.2f%%", (float)100 * pkt_errors / pmch_pkt_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,
ue_dl.pdsch_cfg.grant.mcs[1].tbs);
PRINT_LINE(" TB 0: mcs=%d; tbs=%d", pdsch_cfg.grant.tb[0].mcs_idx, pdsch_cfg.grant.tb[0].tbs);
PRINT_LINE(" TB 1: mcs=%d; tbs=%d", pdsch_cfg.grant.tb[1].mcs_idx, pdsch_cfg.grant.tb[1].tbs);
/* MIMO: if tx and rx antennas are bigger than 1 */
if (cell.nof_ports > 1 && ue_dl.pdsch.nof_rx_antennas > 1) {
uint32_t ri = 0;
float cn = 0;
/* Compute condition number */
if (srslte_ue_dl_ri_select(&ue_dl, NULL, &cn)) {
if (srslte_ue_dl_select_ri(&ue_dl, &ri, &cn)) {
/* Condition number calculation is not supported for the number of tx & rx antennas*/
PRINT_LINE(" κ: NA");
} else {
/* Print condition number */
PRINT_LINE(" κ: %.1f dB (Condition number, 0 dB => Best)", cn);
}
}
PRINT_LINE("");
/* Spatial multiplex only */
if (ue_dl.pdsch_cfg.mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
/* Compute Rank Indicator (RI) and Precoding Matrix Indicator (PMI) */
if (!srslte_ue_dl_ri_pmi_select(&ue_dl, &ri, &pmi, NULL)) {
for (uint32_t nl = 0; nl < SRSLTE_MAX_LAYERS; nl++) {
for (uint32_t cb = 0; cb < SRSLTE_MAX_CODEBOOKS; cb++) {
sinr[nl][cb] = SRSLTE_VEC_EMA(ue_dl.sinr[nl][cb], sinr[nl][cb], 0.5f);
PRINT_LINE(" κ: %.1f dB, RI=%d (Condition number, 0 dB => Best)", cn, ri);
}
}
/* Print Multiplex stats */
PRINT_LINE("SINR (dB) Vs RI and PMI:");
PRINT_LINE(" | RI | 1 | 2 |");
PRINT_LINE(" -------+-------+-------+");
PRINT_LINE(" P | 0 | %5.2f%c| %5.2f%c|", 10 * log10(sinr[0][0]), (ri == 1 && pmi == 0) ? '*' : ' ',
10 * log10(sinr[1][0]), (ri == 2 && pmi == 0) ? '*' : ' ');
PRINT_LINE(" M | 1 | %5.2f%c| %5.2f%c|", 10 * log10(sinr[0][1]), (ri == 1 && pmi == 1) ? '*' : ' ',
10 * log10(sinr[1][1]), (ri == 2 && pmi == 1) ? '*' : ' ');
PRINT_LINE(" I | 2 | %5.2f%c|-------+ ", 10 * log10(sinr[0][2]), (ri == 1 && pmi == 2) ? '*' : ' ');
PRINT_LINE(" | 3 | %5.2f%c| ", 10 * log10(sinr[0][3]), (ri == 1 && pmi == 3) ? '*' : ' ');
PRINT_LINE("");
}
}
PRINT_LINE("Press enter maximum printing debug log of 1 subframe.");
PRINT_LINE("");
PRINT_LINE_RESET_CURSOR();
@ -876,50 +928,45 @@ int main(int argc, char **argv) {
}
break;
}
if (sfidx == 9) {
if (sf_idx == 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.pmch_pkt_errors = 0;
ue_dl.pmch_pkts_total = 0;
/*
ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0;
nof_trials = 0;
*/
pkt_errors = 0;
pkt_total = 0;
pmch_pkt_errors = 0;
pmch_pkt_total = 0;
}
}
#ifndef DISABLE_GRAPHICS
#ifdef ENABLE_GUI
if (!prog_args.disable_plots) {
if ((sfn % 3) == 0 && decode_pdsch) {
plot_sf_idx = srslte_ue_sync_get_sfidx(&ue_sync);
plot_sf_idx = sf_idx;
plot_track = true;
sem_post(&plot_sem);
}
}
#endif
#endif /* ENABLE_GUI */
} else if (ret == 0) {
printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r",
srslte_sync_get_peak_value(&ue_sync.sfind),
ue_sync.frame_total_cnt, ue_sync.state);
#ifndef DISABLE_GRAPHICS
ue_sync.frame_total_cnt,
ue_sync.state);
#ifdef ENABLE_GUI
if (!prog_args.disable_plots) {
plot_sf_idx = srslte_ue_sync_get_sfidx(&ue_sync);
plot_track = false;
sem_post(&plot_sem);
}
#endif
#endif /* ENABLE_GUI */
}
sf_cnt++;
} // Main loop
#ifndef DISABLE_GRAPHICS
#ifdef ENABLE_GUI
if (!prog_args.disable_plots) {
if (!pthread_kill(plot_thread, 0)) {
pthread_kill(plot_thread, SIGHUP);
@ -951,18 +998,10 @@ int main(int argc, char **argv) {
exit(0);
}
/**********************************************************************
* Plotting Functions
***********************************************************************/
#ifndef DISABLE_GRAPHICS
#ifdef ENABLE_GUI
plot_real_t p_sync, pce;
plot_scatter_t pscatequal, pscatequal_pdcch, pscatequal_pmch;
@ -975,7 +1014,6 @@ void *plot_thread_run(void *arg) {
int i;
uint32_t nof_re = SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp);
sdrgui_init();
plot_scatter_init(&pscatequal);
@ -985,7 +1023,6 @@ void *plot_thread_run(void *arg) {
plot_scatter_addToWindowGrid(&pscatequal, (char*)"pdsch_ue", 0, 0);
if (enable_mbsfn_plot) {
plot_scatter_init(&pscatequal_pmch);
plot_scatter_setTitle(&pscatequal_pmch, "PMCH - Equalized Symbols");
@ -1017,11 +1054,10 @@ void *plot_thread_run(void *arg) {
while (1) {
sem_wait(&plot_sem);
uint32_t nof_symbols = ue_dl.pdsch_cfg.nbits[0].nof_re;
uint32_t nof_symbols_pmch = ue_dl.pmch_cfg.nbits[0].nof_re;
uint32_t nof_symbols = pdsch_cfg.grant.nof_re;
if (!prog_args.disable_plots_except_constellation) {
for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i]));
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[0][i]));
if (isinf(tmp_plot[i])) {
tmp_plot[i] = -80;
}
@ -1030,7 +1066,7 @@ void *plot_thread_run(void *arg) {
bzero(tmp_plot2, sizeof(float) * sz);
int g = (sz - 12 * ue_dl.cell.nof_prb) / 2;
for (i = 0; i < 12 * ue_dl.cell.nof_prb; i++) {
tmp_plot2[g+i] = 20 * log10(cabs(ue_dl.ce[0][i]));
tmp_plot2[g + i] = 20 * log10(cabs(ue_dl.chest_res.ce[0][0][i]));
if (isinf(tmp_plot2[g + i])) {
tmp_plot2[g + i] = -80;
}
@ -1047,14 +1083,14 @@ void *plot_thread_run(void *arg) {
pss_obj->frame_size + pss_obj->fft_size - 1);
plot_real_setNewData(&p_sync, tmp_plot2, pss_obj->frame_size);
} else {
int max = srslte_vec_max_fi(ue_sync.sfind.pss.conv_output_avg, ue_sync.sfind.pss.frame_size+ue_sync.sfind.pss.fft_size-1);
int max = srslte_vec_max_fi(ue_sync.sfind.pss.conv_output_avg,
ue_sync.sfind.pss.frame_size + ue_sync.sfind.pss.fft_size - 1);
srslte_vec_sc_prod_fff(ue_sync.sfind.pss.conv_output_avg,
1 / ue_sync.sfind.pss.conv_output_avg[max],
tmp_plot2,
ue_sync.sfind.pss.frame_size + ue_sync.sfind.pss.fft_size - 1);
plot_real_setNewData(&p_sync, tmp_plot2, ue_sync.sfind.pss.frame_size);
}
}
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36 * ue_dl.pdcch.nof_cce[0]);
@ -1063,22 +1099,21 @@ void *plot_thread_run(void *arg) {
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols);
if (enable_mbsfn_plot) {
plot_scatter_setNewData(&pscatequal_pmch, ue_dl.pmch.d, nof_symbols_pmch);
plot_scatter_setNewData(&pscatequal_pmch, ue_dl.pmch.d, nof_symbols);
}
if (plot_sf_idx == 1) {
if (prog_args.net_port_signal > 0) {
srslte_netsink_write(&net_sink_signal, &sf_buffer[srslte_ue_sync_sf_len(&ue_sync)/7],
srslte_ue_sync_sf_len(&ue_sync));
srslte_netsink_write(
&net_sink_signal, &sf_buffer[srslte_ue_sync_sf_len(&ue_sync) / 7], srslte_ue_sync_sf_len(&ue_sync));
}
}
}
return NULL;
}
void init_plots() {
void init_plots()
{
if (sem_init(&plot_sem, 0, 0)) {
perror("sem_init");
@ -1097,4 +1132,4 @@ void init_plots() {
}
}
#endif
#endif /* ENABLE_GUI */

@ -128,11 +128,11 @@ int main(int argc, char **argv) {
printf("Initializing...");fflush(stdout);
if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
fprintf(stderr, "Error opening file %s\n", input_file_name);
ERROR("Error opening file %s\n", input_file_name);
exit(-1);
}
if (srslte_filesink_init(&fsink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
fprintf(stderr, "Error opening file %s\n", output_file_name);
ERROR("Error opening file %s\n", output_file_name);
exit(-1);
}
@ -153,7 +153,7 @@ int main(int argc, char **argv) {
}
if (srslte_cfo_init(&cfocorr, frame_length)) {
fprintf(stderr, "Error initiating CFO\n");
ERROR("Error initiating CFO\n");
return -1;
}
@ -164,19 +164,19 @@ int main(int argc, char **argv) {
*/
for (N_id_2=0;N_id_2<3;N_id_2++) {
if (srslte_pss_init(&pss[N_id_2], frame_length)) {
fprintf(stderr, "Error initializing PSS object\n");
ERROR("Error initializing PSS object\n");
exit(-1);
}
if (srslte_pss_set_N_id_2(&pss[N_id_2], N_id_2)) {
fprintf(stderr, "Error initializing N_id_2\n");
ERROR("Error initializing N_id_2\n");
exit(-1);
}
if (srslte_sss_init(&sss[N_id_2], 128)) {
fprintf(stderr, "Error initializing SSS object\n");
ERROR("Error initializing SSS object\n");
exit(-1);
}
if (srslte_sss_set_N_id_2(&sss[N_id_2], N_id_2)) {
fprintf(stderr, "Error initializing N_id_2\n");
ERROR("Error initializing N_id_2\n");
exit(-1);
}
}

@ -125,7 +125,7 @@ int main(int argc, char **argv) {
printf("Opening RF device...\n");
if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
fprintf(stderr, "Error opening rf\n");
ERROR("Error opening rf\n");
exit(-1);
}
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
@ -135,7 +135,7 @@ int main(int argc, char **argv) {
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
printf("Set RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
printf("Set RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, nof_rx_antennas, rf_freq) / 1000000);
printf("Set RX gain: %.2f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain));
float srate = srslte_rf_set_rx_srate(&rf, rf_rate);
if (srate != rf_rate) {
@ -146,7 +146,7 @@ int main(int argc, char **argv) {
}
srate = srslte_rf_set_rx_srate(&rf, rf_rate);
if (srate != rf_rate) {
fprintf(stderr, "Errror setting samplign frequency %.2f MHz\n", rf_rate*1e-6);
ERROR("Errror setting samplign frequency %.2f MHz\n", rf_rate * 1e-6);
exit(-1);
}
}
@ -160,7 +160,7 @@ int main(int argc, char **argv) {
&& keep_running){
n = srslte_rf_recv_with_time_multi(&rf, (void**) buffer, buflen, true, NULL, NULL);
if (n < 0) {
fprintf(stderr, "Error receiving samples\n");
ERROR("Error receiving samples\n");
exit(-1);
}

@ -105,11 +105,11 @@ void parse_args(int argc, char **argv) {
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);
return srslte_rf_recv_with_time_multi(h, (void**) data, nsamples, true, NULL, NULL);
return srslte_rf_recv_with_time_multi(h, (void**)data[0], nsamples, true, NULL, NULL);
}
int main(int argc, char **argv) {
cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL, NULL};
cf_t* buffer[SRSLTE_MAX_PORTS] = {NULL};
int n;
srslte_rf_t rf;
srslte_filesink_t sink;
@ -124,12 +124,12 @@ int main(int argc, char **argv) {
printf("Opening RF device...\n");
if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
fprintf(stderr, "Error opening rf\n");
ERROR("Error opening rf\n");
exit(-1);
}
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
for (int i = 0; i< SRSLTE_MAX_PORTS; i++) {
for (int i = 0; i < nof_rx_antennas; i++) {
buffer[i] = srslte_vec_malloc(3 * sizeof(cf_t) * SRSLTE_SF_LEN_PRB(100));
}
@ -138,7 +138,7 @@ int main(int argc, char **argv) {
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
printf("Set RX freq: %.6f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
printf("Set RX freq: %.6f MHz\n", srslte_rf_set_rx_freq(&rf, nof_rx_antennas, rf_freq) / 1000000);
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain));
int srate = srslte_sampling_freq_hz(nof_prb);
if (srate != -1) {
@ -150,11 +150,11 @@ int main(int argc, char **argv) {
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate);
if (srate_rf != srate) {
fprintf(stderr, "Could not set sampling rate\n");
ERROR("Could not set sampling rate\n");
exit(-1);
}
} else {
fprintf(stderr, "Invalid number of PRB %d\n", nof_prb);
ERROR("Invalid number of PRB %d\n", nof_prb);
exit(-1);
}
srslte_rf_rx_wait_lo_locked(&rf);
@ -170,7 +170,7 @@ int main(int argc, char **argv) {
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
ERROR("Error initiating ue_sync\n");
exit(-1);
}
@ -180,9 +180,9 @@ int main(int argc, char **argv) {
while((subframe_count < nof_subframes || nof_subframes == -1)
&& !stop_capture)
{
n = srslte_ue_sync_zerocopy_multi(&ue_sync, buffer);
n = srslte_ue_sync_zerocopy(&ue_sync, buffer);
if (n < 0) {
fprintf(stderr, "Error receiving samples\n");
ERROR("Error receiving samples\n");
exit(-1);
}
if (n == 1) {
@ -207,7 +207,7 @@ int main(int argc, char **argv) {
srslte_rf_close(&rf);
srslte_ue_sync_free(&ue_sync);
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (int i = 0; i < nof_rx_antennas; i++) {
if (buffer[i]) {
free(buffer[i]);
}

@ -89,7 +89,7 @@ void parse_args(int argc, char **argv) {
case 'p':
nof_prb = atoi(argv[optind]);
if (!srslte_nofprb_isvalid(nof_prb)) {
fprintf(stderr, "Invalid number of UL RB %d\n", nof_prb);
ERROR("Invalid number of UL RB %d\n", nof_prb);
exit(-1);
}
break;
@ -139,7 +139,7 @@ int main(int argc, char **argv) {
srslte_rf_t rf;
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
ERROR("Error opening rf\n");
exit(-1);
}
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
@ -159,8 +159,8 @@ int main(int argc, char **argv) {
printf("Set TX/RX rate: %.2f MHz\n", (float) srate / 1000000);
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_rx_gain));
printf("Set TX gain: %.1f dB\n", srslte_rf_set_tx_gain(&rf, srslte_rf_tx_gain));
printf("Set TX/RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
srslte_rf_set_tx_freq(&rf, rf_freq);
printf("Set TX/RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, 0, rf_freq) / 1000000);
srslte_rf_set_tx_freq(&rf, 0, rf_freq);
sleep(1);

@ -28,10 +28,11 @@
#define SRSLTE_BCD_HELPERS_H
#include <ctype.h>
#include <srslte/asn1/rrc_asn1.h>
#include <stdint.h>
#include <string>
#include "srslte/asn1/rrc_asn1.h"
namespace srslte {
/******************************************************************************

@ -0,0 +1,329 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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/.
*
*/
#ifndef SRSLTE_DYN_BITSET_H
#define SRSLTE_DYN_BITSET_H
#include <cstdint>
#include <string>
#define CEILFRAC(x, y) ((((x)-1) / (y)) + 1)
namespace srslte {
template <size_t N, bool reversed = false>
class bounded_bitset
{
typedef uint64_t word_t;
static const size_t bits_per_word = 8 * sizeof(word_t);
public:
constexpr bounded_bitset() : buffer(), cur_size(0) {}
constexpr bounded_bitset(size_t cur_size_) : buffer(), cur_size(cur_size_) {}
constexpr size_t max_size() const noexcept { return N; }
size_t size() const noexcept { return cur_size; }
void resize(size_t new_size) noexcept
{
if (new_size > max_size()) {
printf("ERROR: bitset resize out of bounds: %lu>=%lu\n", max_size(), new_size);
return;
}
cur_size = new_size;
sanitize_();
for (size_t i = nof_words_(); i < sizeof(buffer); ++i) {
get_word_(i) = static_cast<word_t>(0);
}
}
void set(size_t pos) noexcept
{
if (pos >= size()) {
printf("ERROR: bitset out of bounds: %lu>=%lu\n", pos, size());
return;
}
pos = reversed ? size() - 1 - pos : pos;
get_word_(pos) |= maskbit(pos);
}
void reset(size_t pos) noexcept
{
if (pos >= size()) {
printf("ERROR: bitset out of bounds: %lu>=%lu\n", pos, size());
return;
}
pos = reversed ? size() - 1 - pos : pos;
get_word_(pos) &= ~(maskbit(pos));
}
void reset() noexcept
{
for (size_t i = 0; i < nof_words_(); ++i) {
buffer[i] = static_cast<word_t>(0);
}
}
bool test(size_t pos) const noexcept
{
if (pos >= size()) {
printf("ERROR: bitset out of bounds: %lu>=%lu\n", pos, size());
return false;
}
return test_(pos);
}
bounded_bitset<N, reversed>& flip() noexcept
{
for (size_t i = 0; i < nof_words_(); ++i) {
buffer[i] = ~buffer[i];
}
sanitize_();
return *this;
}
bounded_bitset<N, reversed>& fill(size_t startpos, size_t endpos, bool value = true) noexcept
{
if (endpos > size() or startpos > endpos) {
printf("ERROR: bounds (%lu, %lu) are not valid for bitset of size: %lu\n", startpos, endpos, size());
return *this;
}
// NOTE: can be optimized
if (value) {
for (size_t i = startpos; i < endpos; ++i) {
set(i);
}
} else {
for (size_t i = startpos; i < endpos; ++i) {
reset(i);
}
}
return *this;
}
bool all() const noexcept
{
const size_t nw = nof_words_();
if (nw == 0) {
return true;
}
word_t allset = ~static_cast<word_t>(0);
for (size_t i = 0; i < nw - 1; i++) {
if (buffer[i] != allset) {
return false;
}
}
return buffer[nw - 1] == (allset >> (nw * bits_per_word - size()));
}
bool any() const noexcept
{
for (size_t i = 0; i < nof_words_(); ++i) {
if (buffer[i] != static_cast<word_t>(0)) {
return true;
}
}
return false;
}
bool any(size_t start, size_t stop) const noexcept
{
if (start > stop or stop > size()) {
printf("ERROR: bounds (%lu, %lu) are not valid for bitset of size: %lu\n", start, stop, size());
return false;
}
// NOTE: can be optimized
for (size_t i = start; i < stop; ++i) {
if (test_(i)) {
return true;
}
}
return false;
}
bool none() const noexcept { return !any(); }
size_t count() const noexcept
{
size_t result = 0;
for (size_t i = 0; i < nof_words_(); i++) {
// result += __builtin_popcountl(buffer[i]);
word_t w = buffer[i];
for (; w; w >>= 1) {
result += (w & 1);
}
}
return result;
}
bool operator==(bounded_bitset<N, reversed>& other) const noexcept
{
if (size() != other.size()) {
return false;
}
for (uint32_t i = 0; i < nof_words_(); ++i) {
if (buffer[i] != other.buffer[i])
return false;
}
return true;
}
bool operator!=(bounded_bitset<N, reversed>& other) const noexcept { return not(*this == other); }
bounded_bitset<N, reversed>& operator|=(const bounded_bitset<N, reversed>& other) noexcept
{
if (other.size() != size()) {
printf("ERROR: operator|= called for bitsets of different sizes (%lu!=%lu)\n", size(), other.size());
return *this;
}
for (size_t i = 0; i < nof_words_(); ++i) {
buffer[i] |= other.buffer[i];
}
return *this;
}
bounded_bitset<N, reversed>& operator&=(const bounded_bitset<N, reversed>& other) noexcept
{
if (other.size() != size()) {
printf("ERROR: operator&= called for bitsets of different sizes (%lu!=%lu)\n", size(), other.size());
return *this;
}
for (size_t i = 0; i < nof_words_(); ++i) {
buffer[i] &= other.buffer[i];
}
return *this;
}
bounded_bitset<N, reversed> operator~() const noexcept
{
bounded_bitset<N, reversed> ret(*this);
ret.flip();
return ret;
}
std::string to_string() const noexcept
{
std::string s;
s.assign(size(), '0');
if (not reversed) {
for (size_t i = size(); i > 0; --i) {
if (test(i - 1)) {
s[size() - i] = '1';
}
}
} else {
for (size_t i = 0; i < size(); ++i) {
if (test(i)) {
s[i] = '1';
}
}
}
return s;
}
uint64_t to_uint64() const noexcept
{
if (nof_words_() > 1) {
printf("ERROR: cannot convert bitset of size %lu bits to uint64_t\n", size());
return 0;
}
return get_word_(0);
}
std::string to_hex() const noexcept
{
size_t nof_digits = (size() - 1) / 4 + 1;
char cstr[CEILFRAC(CEILFRAC(N, bits_per_word) * bits_per_word, 4) + 1];
size_t count = 0;
for (int i = nof_words_() - 1; i >= 0; --i) {
count += sprintf(&cstr[count], "%016lx", buffer[i]);
}
size_t skip = nof_words_() * bits_per_word / 4 - nof_digits;
// printf("bitstring: %s\n", to_string().c_str());
return std::string(&cstr[skip], &cstr[nof_digits + skip + 1]);
}
private:
word_t buffer[(N - 1) / bits_per_word + 1];
size_t cur_size;
void sanitize_()
{
if (N % bits_per_word != 0) {
buffer[nof_words_() - 1] &= ~((~static_cast<word_t>(0)) << (size() % bits_per_word));
}
}
bool test_(size_t pos) const noexcept
{
pos = reversed ? size() - 1 - pos : pos;
return ((get_word_(pos) & maskbit(pos)) != static_cast<word_t>(0));
}
size_t nof_words_() const noexcept { return size() > 0 ? (size() - 1) / bits_per_word + 1 : 0; }
word_t& get_word_(size_t pos) noexcept { return buffer[pos / bits_per_word]; }
const word_t& get_word_(size_t pos) const { return buffer[pos / bits_per_word]; }
size_t word_idx_(size_t pos) const { return pos / bits_per_word; }
static word_t maskbit(size_t pos) { return (static_cast<word_t>(1)) << (pos % bits_per_word); }
};
template <size_t N, bool reversed>
inline bounded_bitset<N, reversed> operator&(const bounded_bitset<N, reversed>& lhs,
const bounded_bitset<N, reversed>& rhs)noexcept
{
bounded_bitset<N, reversed> res(lhs);
res &= rhs;
return res;
}
template <size_t N, bool reversed>
inline bounded_bitset<N, reversed> operator|(const bounded_bitset<N, reversed>& lhs,
const bounded_bitset<N, reversed>& rhs) noexcept
{
bounded_bitset<N, reversed> res(lhs);
res |= rhs;
return res;
}
template <size_t N, bool reversed>
inline bounded_bitset<N, reversed> fliplr(const bounded_bitset<N, reversed>& other) noexcept
{
bounded_bitset<N, reversed> ret(other.size());
ret.reset();
for (uint32_t i = 0; i < ret.size(); ++i) {
if (other.test(i)) {
ret.set(ret.size() - 1 - i);
}
}
return ret;
}
} // namespace srslte
#endif // SRSLTE_DYN_BITSET_H

@ -46,18 +46,24 @@
#define SRSLTE_N_MCH_LCIDS 32
#define HARQ_DELAY_MS 4
#define MSG3_DELAY_MS 2 // Delay added to HARQ_DELAY_MS
#define TTI_RX(tti) (tti>HARQ_DELAY_MS?((tti-HARQ_DELAY_MS)%10240):(10240+tti-HARQ_DELAY_MS))
#define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240)
#define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240)
#define TX_DELAY 4
#define MSG3_DELAY_MS 2 // Delay added to TX_DELAY
#define UL_PIDOF(tti) (tti%(2*HARQ_DELAY_MS))
#define TTI_SUB(a, b) ((((a) + 10240) - (b)) % 10240)
#define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20)
#define TTI_TX(tti) ((tti + TX_DELAY) % 10240)
// Use only in FDD mode!!
#define FDD_HARQ_DELAY_MS 4
#define TTI_RX(tti) (TTI_SUB(tti, FDD_HARQ_DELAY_MS))
#define TTI_RX_ACK(tti) ((tti + (2 * FDD_HARQ_DELAY_MS)) % 10240)
#define TTIMOD_SZ 20
#define TTIMOD(tti) (tti%TTIMOD_SZ)
#define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4)
#define PHICH_MAX_SF 6 // Maximum PHICH in a subframe (1 in FDD, > 1 in TDD, see table 9.1.2-1 36.213)
#define ASYNC_DL_SCHED (FDD_HARQ_DELAY_MS <= 4)
// Cat 4 UE - Max number of DL-SCH transport block bits received within a TTI
// 3GPP 36.306 Table 4.1.1
@ -76,8 +82,6 @@
#define pool_allocate_blocking (pool->allocate(NULL, true))
#endif
#define ZERO_OBJECT(x) memset(&(x), 0x0, sizeof((x)))
#include "srslte/srslte.h"
/*******************************************************************************

@ -1,3 +1,24 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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/.
*
*/
#ifndef SRSLTE_LIBLTE_SSL_H
#define SRSLTE_LIBLTE_SSL_H

@ -81,7 +81,7 @@ public:
void set_time_src(time_itf *source, time_format_t format);
private:
protected:
logger *logger_h;
bool do_tti;

@ -1,3 +1,23 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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: metrics_hub.h

@ -1,3 +1,24 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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/.
*
*/
#ifndef SRSLTE_NAS_PCAP_H
#define SRSLTE_NAS_PCAP_H

@ -224,19 +224,29 @@ public:
virtual ~sch_subh(){}
/* 3GPP 36.321 (R.10) Combined Tables 6.2.1-1, 6.2.1-2, 6.2.1-4 */
typedef enum {
PHR_REPORT = 26,
CRNTI = 27,
CON_RES_ID = 28,
MTCH_MAX_LCID = 28,
TRUNC_BSR = 28,
TA_CMD = 29,
SHORT_BSR = 29,
DRX_CMD = 30,
LONG_BSR = 30,
MCH_SCHED_INFO = 30,
PADDING = 31,
SDU = 0
/* Values of LCID for DL-SCH */
SCELL_ACTIVATION = 0b11011,
CON_RES_ID = 0b11100,
TA_CMD = 0b11101,
DRX_CMD = 0b11110,
/* Values of LCID for UL-SCH */
PHR_REPORT_EXT = 0b11001,
PHR_REPORT = 0b11010,
CRNTI = 0b11011,
TRUNC_BSR = 0b11100,
SHORT_BSR = 0b11101,
LONG_BSR = 0b11110,
/* Values of LCID for MCH */
MTCH_MAX_LCID = 0b11100,
MCH_SCHED_INFO = 0b11110,
/* Common */
PADDING = 0b11111,
SDU = 0b00000
} cetype;
// Size of MAC CEs
@ -260,6 +270,7 @@ public:
uint16_t get_c_rnti();
uint64_t get_con_res_id();
uint8_t get_ta_cmd();
uint8_t get_activation_deactivation_cmd();
float get_phr();
int get_bsr(uint32_t buff_size[4]);

@ -49,7 +49,7 @@ public:
class process_callback
{
public:
virtual void process_pdu(uint8_t *buff, uint32_t len, channel_t channel, uint32_t tstamp) = 0;
virtual void process_pdu(uint8_t* buff, uint32_t len, channel_t channel) = 0;
};
pdu_queue(uint32_t pool_size = DEFAULT_POOL_SIZE) : pool(pool_size), callback(NULL), log_h(NULL) {}
@ -57,7 +57,7 @@ public:
uint8_t* request(uint32_t len);
void deallocate(uint8_t* pdu);
void push(uint8_t *ptr, uint32_t len, channel_t channel = DCH, uint32_t tstamp = 0);
void push(uint8_t* ptr, uint32_t len, channel_t channel = DCH);
bool process_pdus();
@ -68,7 +68,6 @@ private:
typedef struct {
uint8_t ptr[MAX_PDU_LEN];
uint32_t len;
uint32_t tstamp;
channel_t channel;
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
char debug_name[128];

@ -40,6 +40,8 @@
#include <vector>
#include <time.h>
#include "srslte/srslte.h"
namespace srslte {
class timer_callback
@ -143,12 +145,12 @@ public:
used_timers[i] = false;
nof_used_timers--;
} else {
fprintf(stderr, "Error releasing timer id=%d: nof_used_timers=%d, nof_timers=%d\n", i, nof_used_timers, nof_timers);
ERROR("Error releasing timer id=%d: nof_used_timers=%d, nof_timers=%d\n", i, nof_used_timers, nof_timers);
}
}
uint32_t get_unique_id() {
if (nof_used_timers >= nof_timers) {
fprintf(stderr, "Error getting unique timer id: no more timers available\n");
ERROR("Error getting unique timer id: no more timers available\n");
return 0;
} else {
for (uint32_t i=0;i<nof_timers;i++) {
@ -158,8 +160,9 @@ public:
return i;
}
}
fprintf(stderr, "Error getting unique timer id: no more timers available but nof_used_timers=%d, nof_timers=%d\n",
nof_used_timers, nof_timers);
ERROR("Error getting unique timer id: no more timers available but nof_used_timers=%d, nof_timers=%d\n",
nof_used_timers,
nof_timers);
return 0;
}
}

@ -48,19 +48,39 @@ public:
const static int MAX_GRANTS = 64;
typedef struct {
srslte_enb_dl_pdsch_t sched_grants[MAX_GRANTS];
srslte_dci_dl_t dci;
srslte_dci_cfg_t dci_cfg;
uint8_t* data[SRSLTE_MAX_TB];
srslte_softbuffer_tx_t* softbuffer_tx[SRSLTE_MAX_TB];
} dl_sched_grant_t;
typedef struct {
dl_sched_grant_t pdsch[MAX_GRANTS];
uint32_t nof_grants;
uint32_t cfi;
} dl_sched_t;
typedef struct {
srslte_enb_ul_pusch_t sched_grants[MAX_GRANTS];
srslte_enb_dl_phich_t phich[MAX_GRANTS];
uint16_t rnti;
bool ack;
} ul_sched_ack_t;
typedef struct {
srslte_dci_ul_t dci;
srslte_dci_cfg_t dci_cfg;
uint32_t current_tx_nb;
uint8_t* data;
bool needs_pdcch;
srslte_softbuffer_rx_t* softbuffer_rx;
} ul_sched_grant_t;
typedef struct {
ul_sched_grant_t pusch[MAX_GRANTS];
ul_sched_ack_t phich[MAX_GRANTS];
uint32_t nof_grants;
uint32_t nof_phich;
} ul_sched_t;
virtual int sr_detected(uint32_t tti, uint16_t rnti) = 0;
virtual int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv) = 0;
@ -72,7 +92,7 @@ public:
virtual int crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc_res) = 0;
virtual int get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) = 0;
virtual int get_mch_sched(bool is_mcch, dl_sched_t *dl_sched_res) = 0;
virtual int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res) = 0;
virtual int get_ul_sched(uint32_t tti, ul_sched_t *ul_sched_res) = 0;
// Radio-Link status
@ -88,8 +108,9 @@ class phy_interface_mac
public:
/* MAC adds/removes an RNTI to the list of active RNTIs */
virtual int add_rnti(uint16_t rnti) = 0;
virtual int add_rnti(uint16_t rnti, bool is_temporal = false) = 0;
virtual void rem_rnti(uint16_t rnti) = 0;
virtual void set_mch_period_stop(uint32_t stop) = 0;
};
/* Interface RRC -> PHY */
@ -109,7 +130,6 @@ public:
virtual void configure_mbsfn(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13,
asn1::rrc::mcch_msg_s mcch) = 0;
virtual void set_conf_dedicated_ack(uint16_t rnti, bool rrc_completed) = 0;
virtual void set_config_dedicated(uint16_t rnti, asn1::rrc::phys_cfg_ded_s* dedicated) = 0;
};

@ -18,6 +18,7 @@
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLTE_EPC_INTERFACES_H
#define SRSLTE_EPC_INTERFACES_H

@ -24,6 +24,7 @@
*
*/
#include "srslte/common/common.h"
#include "srslte/srslte.h"
#ifndef SRSLTE_SCHED_INTERFACE_H
@ -104,24 +105,16 @@ public:
typedef struct {
bool continuous_pusch;
/* ue capabilities, etc */
uint32_t maxharq_tx;
uint32_t aperiodic_cqi_period; // if 0 is periodic CQI
uint32_t beta_ack_index;
uint32_t beta_ri_index;
uint32_t beta_cqi_index;
bool continuous_pusch;
srslte_uci_offset_cfg_t uci_offset;
srslte_pucch_cfg_t pucch_cfg;
uint32_t n_pucch_cqi;
uint32_t sr_I;
uint32_t sr_N_pucch;
bool sr_enabled;
uint32_t cqi_pucch;
uint32_t cqi_idx;
bool cqi_enabled;
uint32_t aperiodic_cqi_period; // if 0 is periodic CQI
srslte_dl_cfg_t dl_cfg;
ue_bearer_cfg_t ue_bearers[MAX_LC];
@ -149,10 +142,7 @@ public:
} dl_pdu_mch_t;
typedef struct {
uint32_t rnti;
srslte_dci_format_t dci_format;
srslte_ra_dl_dci_t dci;
srslte_dci_location_t dci_location;
srslte_dci_dl_t dci;
uint32_t tbs[SRSLTE_MAX_TB];
bool mac_ce_ta;
bool mac_ce_rnti;
@ -161,12 +151,10 @@ public:
} dl_sched_data_t;
typedef struct {
uint32_t rnti;
bool needs_pdcch;
uint32_t current_tx_nb;
uint32_t tbs;
srslte_ra_ul_dci_t dci;
srslte_dci_location_t dci_location;
srslte_dci_ul_t dci;
} ul_sched_data_t;
typedef struct {
@ -175,17 +163,14 @@ public:
} dl_sched_rar_grant_t;
typedef struct {
uint32_t rarnti;
uint32_t tbs;
srslte_ra_dl_dci_t dci;
srslte_dci_location_t dci_location;
srslte_dci_dl_t dci;
uint32_t nof_grants;
dl_sched_rar_grant_t grants[MAX_RAR_LIST];
dl_sched_rar_grant_t msg3_grant[MAX_RAR_LIST];
} dl_sched_rar_t;
typedef struct {
srslte_ra_dl_dci_t dci;
srslte_dci_location_t dci_location;
srslte_dci_dl_t dci;
enum bc_type {
BCCH, PCCH

@ -345,9 +345,6 @@ public:
/* MUX calls BSR to let it generate a padding BSR if there is space in PDU */
virtual bool generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t *bsr) = 0;
/* MAX calls BSR to set the Tx TTI */
virtual void set_tx_tti(uint32_t tti) = 0;
};
@ -362,88 +359,79 @@ public:
uint32_t nof_mbsfn_services;
} mac_phy_cfg_mbsfn_t;
typedef struct {
uint32_t tbs;
bool ndi;
bool ndi_present;
int rv;
} mac_tb_t;
typedef struct {
mac_tb_t tb[SRSLTE_MAX_TB];
uint32_t pid;
uint32_t tti;
uint32_t last_tti;
bool ndi[SRSLTE_MAX_CODEWORDS];
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;
bool has_cqi_request;
srslte_rnti_type_t rnti_type;
srslte_phy_grant_t phy_grant;
} mac_grant_t;
} mac_grant_dl_t;
typedef struct {
bool decode_enabled[SRSLTE_MAX_TB];
int rv[SRSLTE_MAX_TB];
mac_tb_t tb;
uint32_t pid;
uint16_t rnti;
bool phich_available;
bool hi_value;
} mac_grant_ul_t;
typedef struct {
bool enabled;
uint32_t rv;
uint8_t* payload;
union {
srslte_softbuffer_rx_t* rx;
srslte_softbuffer_tx_t* tx;
} softbuffer;
} tb_action_t;
typedef struct {
tb_action_t tb[SRSLTE_MAX_TB];
bool generate_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;
uint8_t *payload_ptr[SRSLTE_MAX_TB];
srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_TB];
srslte_phy_grant_t phy_grant;
} tb_action_dl_t;
typedef struct {
bool tx_enabled;
bool expect_ack;
uint32_t rv[SRSLTE_MAX_TB];
uint16_t rnti;
tb_action_t tb;
uint32_t current_tx_nb;
int32_t tti_offset; // relative offset between grant and UL tx/HARQ rx
srslte_softbuffer_tx_t *softbuffers;
srslte_phy_grant_t phy_grant;
uint8_t *payload_ptr[SRSLTE_MAX_TB];
bool expect_ack;
} tb_action_ul_t;
/* Indicate reception of UL grant.
* payload_ptr points to memory where MAC PDU must be written by MAC layer */
virtual void new_grant_ul(mac_grant_t grant, tb_action_ul_t *action) = 0;
/* Indicate reception of UL grant + HARQ information throught PHICH in the same TTI. */
virtual void new_grant_ul_ack(mac_grant_t grant, bool ack, tb_action_ul_t *action) = 0;
/* Obtain action for a new MCH subframe. */
virtual void new_mch_dl(srslte_ra_dl_grant_t phy_grant, tb_action_dl_t *action) = 0;
/* Query the MAC for the current RNTI to look for
*/
virtual uint16_t get_dl_sched_rnti(uint32_t tti) = 0;
virtual uint16_t get_ul_sched_rnti(uint32_t tti) = 0;
/* Indicate reception of HARQ information only through PHICH. */
virtual void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action) = 0;
/* Indicate reception of UL dci.
* payload_ptr points to memory where MAC PDU must be written by MAC layer */
virtual void new_grant_ul(uint32_t cc_idx, mac_grant_ul_t grant, tb_action_ul_t* action) = 0;
/* Indicate reception of DL grant. */
virtual void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) = 0;
/* Indicate reception of DL dci. */
virtual void new_grant_dl(uint32_t cc_idx, mac_grant_dl_t grant, tb_action_dl_t* action) = 0;
/* Indicate successful decoding of PDSCH TB. */
virtual void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid) = 0;
/* Indicate successful decoding of PDSCH AND PCH TB. */
virtual void tb_decoded(uint32_t cc_idx, mac_grant_dl_t grant, bool ack[SRSLTE_MAX_CODEWORDS]) = 0;
/* Indicate successful decoding of BCH TB through PBCH */
virtual void bch_decoded_ok(uint8_t *payload, uint32_t len) = 0;
/* Indicate successful decoding of PCH TB through PDSCH */
virtual void pch_decoded_ok(uint32_t len) = 0;
/* Indicate successful decoding of MCH TB through PMCH */
virtual void mch_decoded_ok(uint32_t len) = 0;
virtual void mch_decoded(uint32_t len, bool crc) = 0;
/* Obtain action for a new MCH subframe. */
virtual void new_mch_dl(srslte_pdsch_grant_t phy_grant, tb_action_dl_t* action) = 0;
/* Communicate the number of mbsfn services available */
virtual void set_mbsfn_config(uint32_t nof_mbsfn_services) = 0;
/* Function called every start of a subframe (TTI). Warning, this function is called
* from a high priority thread and should terminate asap
*/
/* Indicate new TTI */
virtual void run_tti(const uint32_t tti) = 0;
};
/* Interface RRC -> MAC shared between different RATs */
@ -453,35 +441,186 @@ public:
// Class to handle UE specific RNTIs between RRC and MAC
typedef struct {
uint16_t crnti;
uint16_t rar_rnti;
uint16_t temp_rnti;
uint16_t tpc_rnti;
uint16_t sps_rnti;
uint64_t contention_id;
} ue_rnti_t;
typedef struct {
typedef struct ul_harq_cfg_t {
uint32_t max_harq_msg3_tx;
uint32_t max_harq_tx;
} ul_harq_params_t;
ul_harq_cfg_t() { reset(); }
void reset()
{
max_harq_msg3_tx = 5;
max_harq_tx = 5;
}
} ul_harq_cfg_t;
};
/* Interface RRC -> MAC */
class mac_interface_rrc : public mac_interface_rrc_common
{
public:
typedef struct bsr_cfg_t {
int periodic_timer;
int retx_timer;
bsr_cfg_t() { reset(); }
void reset()
{
periodic_timer = -1;
retx_timer = 2560;
}
} bsr_cfg_t;
typedef struct phr_cfg_t {
bool enabled;
int periodic_timer;
int prohibit_timer;
int db_pathloss_change;
bool extended;
phr_cfg_t() { reset(); }
void reset()
{
enabled = false;
periodic_timer = -1;
prohibit_timer = -1;
db_pathloss_change = -1;
extended = false;
}
} phr_cfg_t;
typedef struct sr_cfg_t {
bool enabled;
int dsr_transmax;
sr_cfg_t() { reset(); }
void reset() { enabled = false; }
} sr_cfg_t;
typedef struct rach_cfg_t {
bool enabled;
uint32_t nof_preambles;
uint32_t nof_groupA_preambles;
int32_t messagePowerOffsetGroupB;
uint32_t messageSizeGroupA;
uint32_t responseWindowSize;
uint32_t powerRampingStep;
uint32_t preambleTransMax;
int32_t iniReceivedTargetPower;
uint32_t contentionResolutionTimer;
uint32_t new_ra_msg_len;
rach_cfg_t() { reset(); }
void reset() { enabled = false; }
} rach_cfg_t;
class mac_cfg_t
{
public:
// Default constructor with default values as in 36.331 9.2.2
mac_cfg_t() { time_alignment_timer = -1; }
typedef struct {
asn1::rrc::mac_main_cfg_s main;
asn1::rrc::rach_cfg_common_s rach;
asn1::rrc::sched_request_cfg_c sr;
ul_harq_params_t ul_harq_params;
uint32_t prach_config_index;
} mac_cfg_t;
void set_defaults()
{
bsr_cfg.reset();
phr_cfg.reset();
sr_cfg.reset();
rach_cfg.reset();
harq_cfg.reset();
time_alignment_timer = -1;
}
// Called only if section is present
void set_sched_request_cfg(asn1::rrc::sched_request_cfg_c& cfg)
{
sr_cfg.enabled = cfg.type() == asn1::rrc::setup_e::setup;
if (sr_cfg.enabled) {
sr_cfg.dsr_transmax = cfg.setup().dsr_trans_max.to_number();
}
}
// MAC-MainConfig section is always present
void set_mac_main_cfg(asn1::rrc::mac_main_cfg_s& cfg)
{
// Update values only if each section is present
if (cfg.phr_cfg_present) {
phr_cfg.enabled = cfg.phr_cfg.type() == asn1::rrc::setup_e::setup;
if (phr_cfg.enabled) {
phr_cfg.prohibit_timer = cfg.phr_cfg.setup().prohibit_phr_timer.to_number();
phr_cfg.periodic_timer = cfg.phr_cfg.setup().periodic_phr_timer.to_number();
phr_cfg.db_pathloss_change = cfg.phr_cfg.setup().dl_pathloss_change.to_number();
}
}
if (cfg.mac_main_cfg_v1020_present) {
typedef asn1::rrc::mac_main_cfg_s::mac_main_cfg_v1020_s_ mac_main_cfg_v1020_t;
mac_main_cfg_v1020_t* mac_main_cfg_v1020 = cfg.mac_main_cfg_v1020.get();
phr_cfg.extended = mac_main_cfg_v1020->extended_phr_r10_present;
}
if (cfg.ul_sch_cfg_present) {
bsr_cfg.periodic_timer = cfg.ul_sch_cfg.periodic_bsr_timer.to_number();
bsr_cfg.retx_timer = cfg.ul_sch_cfg.retx_bsr_timer.to_number();
if (cfg.ul_sch_cfg.max_harq_tx_present) {
harq_cfg.max_harq_tx = cfg.ul_sch_cfg.max_harq_tx.to_number();
}
}
// TimeAlignmentDedicated overwrites Common??
time_alignment_timer = cfg.time_align_timer_ded.to_number();
}
// RACH-Common section is always present
void set_rach_cfg_common(asn1::rrc::rach_cfg_common_s& cfg)
{
// Preamble info
rach_cfg.nof_preambles = cfg.preamb_info.nof_ra_preambs.to_number();
if (cfg.preamb_info.preambs_group_a_cfg_present) {
rach_cfg.nof_groupA_preambles = cfg.preamb_info.preambs_group_a_cfg.size_of_ra_preambs_group_a.to_number();
rach_cfg.messageSizeGroupA = cfg.preamb_info.preambs_group_a_cfg.msg_size_group_a.to_number();
rach_cfg.messagePowerOffsetGroupB = cfg.preamb_info.preambs_group_a_cfg.msg_pwr_offset_group_b.to_number();
} else {
rach_cfg.nof_groupA_preambles = 0;
}
// Power ramping
rach_cfg.powerRampingStep = cfg.pwr_ramp_params.pwr_ramp_step.to_number();
rach_cfg.iniReceivedTargetPower = cfg.pwr_ramp_params.preamb_init_rx_target_pwr.to_number();
// Supervision info
rach_cfg.preambleTransMax = cfg.ra_supervision_info.preamb_trans_max.to_number();
rach_cfg.responseWindowSize = cfg.ra_supervision_info.ra_resp_win_size.to_number();
rach_cfg.contentionResolutionTimer = cfg.ra_supervision_info.mac_contention_resolution_timer.to_number();
// HARQ Msg3
harq_cfg.max_harq_msg3_tx = cfg.max_harq_msg3_tx;
}
void set_time_alignment(asn1::rrc::time_align_timer_e time_alignment_timer)
{
this->time_alignment_timer = time_alignment_timer.to_number();
}
bsr_cfg_t& get_bsr_cfg() { return bsr_cfg; }
phr_cfg_t& get_phr_cfg() { return phr_cfg; }
rach_cfg_t& get_rach_cfg() { return rach_cfg; }
sr_cfg_t& get_sr_cfg() { return sr_cfg; }
ul_harq_cfg_t& get_harq_cfg() { return harq_cfg; }
int get_time_alignment_timer() { return time_alignment_timer; }
private:
bsr_cfg_t bsr_cfg;
phr_cfg_t phr_cfg;
sr_cfg_t sr_cfg;
rach_cfg_t rach_cfg;
ul_harq_cfg_t harq_cfg;
int time_alignment_timer;
};
virtual void clear_rntis() = 0;
/* Instructs the MAC to start receiving BCCH */
virtual void bcch_start_rx(int si_window_start, int si_window_length) = 0;
virtual void bcch_stop_rx() = 0;
/* Instructs the MAC to start receiving PCCH */
virtual void pcch_start_rx() = 0;
@ -494,11 +633,7 @@ public:
virtual uint32_t get_current_tti() = 0;
virtual void set_config(mac_cfg_t *mac_cfg) = 0;
virtual void set_config_main(asn1::rrc::mac_main_cfg_s* main_cfg) = 0;
virtual void set_config_rach(asn1::rrc::rach_cfg_common_s* rach_cfg, uint32_t prach_config_index) = 0;
virtual void set_config_sr(asn1::rrc::sched_request_cfg_c* sr_cfg) = 0;
virtual void get_config(mac_cfg_t *mac_cfg) = 0;
virtual void set_config(mac_cfg_t& mac_cfg) = 0;
virtual void get_rntis(ue_rnti_t *rntis) = 0;
virtual void set_contention_id(uint64_t uecri) = 0;
@ -517,17 +652,26 @@ public:
*
*/
typedef struct {
uint32_t radio_idx;
uint32_t channel_idx;
} carrier_map_t;
typedef struct {
bool ul_pwr_ctrl_en;
float prach_gain;
int pdsch_max_its;
bool attach_enable_64qam;
int nof_phy_threads;
int worker_cpu_mask;
int sync_cpu_affinity;
uint32_t ue_category;
uint32_t nof_carriers;
uint32_t nof_radios;
uint32_t nof_rx_ant;
uint32_t nof_rf_channels;
carrier_map_t carrier_map[SRSLTE_MAX_CARRIERS];
std::string equalizer_mode;
int cqi_max;
int cqi_fixed;
@ -546,10 +690,11 @@ typedef struct {
uint32_t sfo_correct_period;
uint32_t cfo_loop_pss_conv;
uint32_t cfo_ref_mask;
bool average_subframe_enabled;
bool interpolate_subframe_enabled;
bool estimator_fil_auto;
float estimator_fil_stddev;
uint32_t estimator_fil_order;
float snr_to_cqi_offset;
std::string sss_algorithm;
bool rssi_sensor_enabled;
bool sic_pss_enabled;
@ -565,7 +710,6 @@ typedef struct {
class phy_interface_mac_common
{
public:
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
virtual void set_crnti(uint16_t rnti) = 0;
@ -573,8 +717,11 @@ public:
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0;
virtual void set_timeadv(uint32_t ta_cmd) = 0;
/* Sets RAR grant payload */
virtual void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) = 0;
/* Activate / Disactivate SCell*/
virtual void set_activation_deactivation_scell(uint32_t cmd) = 0;
/* Sets RAR dci payload */
virtual void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rnti) = 0;
virtual uint32_t get_current_tti() = 0;
@ -586,24 +733,24 @@ public:
class phy_interface_mac : public phy_interface_mac_common
{
public:
typedef struct {
bool is_transmitted;
uint32_t tti_ra;
uint32_t f_id;
uint32_t preamble_format;
} prach_info_t;
/* Configure PRACH using parameters written by RRC */
virtual void configure_prach_params() = 0;
virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0;
virtual int prach_tx_tti() = 0;
virtual prach_info_t prach_get_info() = 0;
/* Indicates the transmission of a SR signal in the next opportunity */
virtual void sr_send() = 0;
virtual int sr_last_tx_tti() = 0;
/* Instruct the PHY to decode PDCCH with the CRC scrambled with given RNTI */
virtual void pdcch_ul_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0;
virtual void pdcch_dl_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0;
virtual void pdcch_ul_search_reset() = 0;
virtual void pdcch_dl_search_reset() = 0;
virtual void set_mch_period_stop(uint32_t stop) = 0;
};
class phy_interface_rrc
@ -632,19 +779,15 @@ public:
asn1::rrc::phys_cfg_ded_s dedicated;
phy_cfg_common_t common;
phy_cfg_mbsfn_t mbsfn;
bool enable_64qam;
} phy_cfg_t;
virtual void get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn = NULL) = 0;
virtual uint32_t get_current_earfcn() = 0;
virtual uint32_t get_current_pci() = 0;
virtual void get_config(phy_cfg_t *phy_cfg) = 0;
virtual void set_config(phy_cfg_t *phy_cfg) = 0;
virtual void set_config_dedicated(asn1::rrc::phys_cfg_ded_s* dedicated) = 0;
virtual void set_config_common(phy_cfg_common_t *common) = 0;
virtual void set_config(phy_cfg_t* config) = 0;
virtual void set_config_scell(asn1::rrc::scell_to_add_mod_r10_s* scell_config) = 0;
virtual void set_config_tdd(asn1::rrc::tdd_cfg_s* tdd) = 0;
virtual void set_config_64qam_en(bool enable) = 0;
virtual void set_config_mbsfn_sib2(asn1::rrc::sib_type2_s* sib2) = 0;
virtual void set_config_mbsfn_sib13(asn1::rrc::sib_type13_r9_s* sib13) = 0;
virtual void set_config_mbsfn_mcch(asn1::rrc::mcch_msg_s* mcch) = 0;
@ -669,9 +812,6 @@ public:
virtual bool cell_select(phy_cell_t *cell = NULL) = 0;
virtual bool cell_is_camping() = 0;
/* Configure UL using parameters written with set_param() */
virtual void configure_ul_params(bool pregen_disabled = false) = 0;
virtual void reset() = 0;
};

@ -30,26 +30,23 @@
#include <stdint.h>
#include "srslte/config.h"
#define SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN 65
#define SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN 64
typedef enum SRSLTE_API {
SRSLTE_CHEST_FILTER_GAUSS = 0,
SRSLTE_CHEST_FILTER_TRIANGLE,
SRSLTE_CHEST_FILTER_NONE
} srslte_chest_filter_t;
SRSLTE_API void srslte_chest_average_pilots(cf_t *input,
cf_t *output,
float *filter,
uint32_t nof_ref,
uint32_t nof_symbols,
uint32_t filter_len);
SRSLTE_API void srslte_chest_average_pilots(
cf_t* input, cf_t* output, float* filter, uint32_t nof_ref, uint32_t nof_symbols, uint32_t filter_len);
SRSLTE_API void srslte_chest_set_smooth_filter3_coeff(float *smooth_filter,
float w);
SRSLTE_API uint32_t srslte_chest_set_smooth_filter3_coeff(float* smooth_filter, float w);
SRSLTE_API float srslte_chest_estimate_noise_pilots(cf_t *noisy,
cf_t *noiseless,
cf_t *noise_vec,
uint32_t nof_pilots);
SRSLTE_API float srslte_chest_estimate_noise_pilots(cf_t* noisy, cf_t* noiseless, cf_t* noise_vec, uint32_t nof_pilots);
SRSLTE_API void srslte_chest_set_triangle_filter(float *fil,
int filter_len);
SRSLTE_API uint32_t srslte_chest_set_triangle_filter(float* fil, int filter_len);
#endif // SRSLTE_CHEST_COMMON_H
SRSLTE_API uint32_t srslte_chest_set_smooth_filter_gauss(float* filter, uint32_t order, float std_dev);
#endif // SRSLTE_CHEST_COMMON_H

@ -51,19 +51,35 @@
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/sync/pss.h"
typedef struct SRSLTE_API {
cf_t* ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
uint32_t nof_re;
float noise_estimate;
float noise_estimate_dbm;
float snr_db;
float rsrp;
float rsrp_dbm;
float rsrp_neigh_dbm;
float rsrp_port_dbm[SRSLTE_MAX_PORTS];
float rsrq;
float rsrq_db;
float rssi_dbm;
float cfo;
} srslte_chest_dl_res_t;
typedef enum {
SRSLTE_NOISE_ALG_REFS,
typedef enum SRSLTE_API {
SRSLTE_NOISE_ALG_REFS = 0,
SRSLTE_NOISE_ALG_PSS,
SRSLTE_NOISE_ALG_EMPTY,
} srslte_chest_dl_noise_alg_t;
typedef struct {
typedef struct SRSLTE_API {
srslte_cell_t cell;
uint32_t nof_rx_antennas;
srslte_refsignal_t csr_refs;
srslte_refsignal_t **mbsfn_refs;
cf_t *pilot_estimates;
cf_t *pilot_estimates_average;
cf_t *pilot_recv_signal;
@ -74,131 +90,72 @@ typedef struct {
float snr_vector[12000];
float pilot_power[12000];
#endif
bool smooth_filter_auto;
uint32_t smooth_filter_len;
float smooth_filter[SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN];
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
srslte_interp_lin_t srslte_interp_lin;
srslte_interp_lin_t srslte_interp_lin_3;
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 rsrp_corr[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
float cfo;
bool rsrp_neighbour;
bool cfo_estimate_enable;
uint32_t cfo_estimate_sf_mask;
/* Use PSS for noise estimation in LS linear interpolation mode */
cf_t pss_signal[SRSLTE_PSS_LEN];
cf_t tmp_pss[SRSLTE_PSS_LEN];
cf_t tmp_pss_noisy[SRSLTE_PSS_LEN];
srslte_chest_dl_noise_alg_t noise_alg;
int last_nof_antennas;
bool average_subframe;
} srslte_chest_dl_t;
typedef struct SRSLTE_API {
SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q,
uint32_t max_prb);
srslte_chest_dl_noise_alg_t noise_alg;
srslte_chest_filter_t filter_type;
float filter_coef[2];
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
uint16_t mbsfn_area_id;
bool interpolate_subframe;
bool rsrp_neighbour;
bool cfo_estimate_enable;
uint32_t cfo_estimate_sf_mask;
} srslte_chest_dl_cfg_t;
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_init(srslte_chest_dl_t* q, uint32_t max_prb, uint32_t nof_rx_antennas);
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,
uint32_t filter_len);
SRSLTE_API int srslte_chest_dl_res_init(srslte_chest_dl_res_t* q, uint32_t max_prb);
SRSLTE_API void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q,
float w);
SRSLTE_API void srslte_chest_dl_res_set_identity(srslte_chest_dl_res_t* q);
SRSLTE_API void srslte_chest_dl_set_smooth_filter_gauss(srslte_chest_dl_t* q,
uint32_t order,
float std_dev);
SRSLTE_API void srslte_chest_dl_res_set_ones(srslte_chest_dl_res_t* q);
SRSLTE_API void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t* q,
bool enable);
SRSLTE_API void srslte_chest_dl_res_free(srslte_chest_dl_res_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);
/* These functions change the internal object state */
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 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);
/* These functions do not change the internal state */
SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t* q,
cf_t *input,
cf_t *ce[SRSLTE_MAX_PORTS],
uint32_t sf_idx);
SRSLTE_API int srslte_chest_dl_estimate_multi_mbsfn(srslte_chest_dl_t *q,
srslte_dl_sf_cfg_t* sf,
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,
uint32_t sf_idx,
uint32_t port_id,
uint32_t rxant_id);
SRSLTE_API void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q,
bool enable,
uint32_t mask);
SRSLTE_API void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q,
bool enable);
SRSLTE_API void srslte_chest_dl_set_rsrp_neighbour(srslte_chest_dl_t *q,
bool rsrp_for_neighbour);
SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q);
SRSLTE_API float srslte_chest_dl_get_cfo(srslte_chest_dl_t *q);
srslte_chest_dl_res_t* res);
SRSLTE_API float srslte_chest_dl_get_snr(srslte_chest_dl_t *q);
SRSLTE_API float srslte_chest_dl_get_snr_ant_port(srslte_chest_dl_t *q,
uint32_t ant_idx,
uint32_t port_idx);
SRSLTE_API float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q);
SRSLTE_API float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q);
SRSLTE_API float srslte_chest_dl_get_rsrq_ant_port(srslte_chest_dl_t *q,
uint32_t ant_idx,
uint32_t port);
SRSLTE_API float srslte_chest_dl_get_rsrp_ant_port(srslte_chest_dl_t *q,
uint32_t ant_idx,
uint32_t port);
SRSLTE_API float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q,
uint32_t port);
SRSLTE_API float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q);
SRSLTE_API int srslte_chest_dl_estimate_cfg(srslte_chest_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_cfg_t* cfg,
cf_t* input[SRSLTE_MAX_PORTS],
srslte_chest_dl_res_t* res);
SRSLTE_API float srslte_chest_dl_get_rsrp_neighbour(srslte_chest_dl_t *q);
/* These functions are exceptions and return values from last call to chest_dl_estimate */
SRSLTE_API float srslte_chest_dl_get_rsrq_ant_port(srslte_chest_dl_t* q, uint32_t ant_idx, uint32_t port_idx);
SRSLTE_API float srslte_chest_dl_get_rsrp_ant_port(srslte_chest_dl_t* q, uint32_t ant_idx, uint32_t port);
#endif // SRSLTE_CHEST_DL_H

@ -44,9 +44,21 @@
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/chest_common.h"
#include "srslte/phy/resampling/interp.h"
#include "srslte/phy/ch_estimation/refsignal_ul.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/phch/pucch_cfg.h"
#include "srslte/phy/phch/pusch_cfg.h"
#include "srslte/phy/resampling/interp.h"
typedef struct SRSLTE_API {
cf_t* ce;
uint32_t nof_re;
float noise_estimate;
float noise_estimate_dbm;
float snr;
float snr_db;
float cfo;
} srslte_chest_ul_res_t;
typedef struct {
srslte_cell_t cell;
@ -70,9 +82,6 @@ typedef struct {
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
float pilot_power;
float noise_estimate;
} srslte_chest_ul_t;
@ -81,41 +90,20 @@ SRSLTE_API int srslte_chest_ul_init(srslte_chest_ul_t *q,
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_set_cfg(srslte_chest_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg);
SRSLTE_API void srslte_chest_ul_set_smooth_filter(srslte_chest_ul_t *q,
float *filter,
uint32_t filter_len);
SRSLTE_API int srslte_chest_ul_res_init(srslte_chest_ul_res_t* q, uint32_t max_prb);
SRSLTE_API void srslte_chest_ul_set_smooth_filter3_coeff(srslte_chest_ul_t* q,
float w);
SRSLTE_API void srslte_chest_ul_res_set_identity(srslte_chest_ul_res_t* q);
SRSLTE_API int srslte_chest_ul_estimate(srslte_chest_ul_t *q,
cf_t *input,
cf_t *ce,
uint32_t nof_prb,
uint32_t sf_idx,
uint32_t cyclic_shift_for_dmrs,
uint32_t n_prb[2]);
SRSLTE_API void srslte_chest_ul_res_free(srslte_chest_ul_res_t* q);
SRSLTE_API int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q,
cf_t *input,
cf_t *ce,
srslte_pucch_format_t format,
uint32_t n_pucch,
uint32_t sf_idx,
uint8_t *pucch2_ack_bits);
SRSLTE_API int srslte_chest_ul_set_cell(srslte_chest_ul_t* q, srslte_cell_t cell);
SRSLTE_API float srslte_chest_ul_get_noise_estimate(srslte_chest_ul_t *q);
SRSLTE_API void srslte_chest_ul_pregen(srslte_chest_ul_t* q, srslte_refsignal_dmrs_pusch_cfg_t* cfg);
SRSLTE_API float srslte_chest_ul_get_snr(srslte_chest_ul_t *q);
SRSLTE_API int srslte_chest_ul_estimate_pusch(
srslte_chest_ul_t* q, srslte_ul_sf_cfg_t* sf, srslte_pusch_cfg_t* cfg, cf_t* input, srslte_chest_ul_res_t* res);
SRSLTE_API int srslte_chest_ul_estimate_pucch(
srslte_chest_ul_t* q, srslte_ul_sf_cfg_t* sf, srslte_pucch_cfg_t* cfg, cf_t* input, srslte_chest_ul_res_t* res);
#endif // SRSLTE_CHEST_UL_H

@ -39,10 +39,9 @@
#include "srslte/phy/common/phy_common.h"
// 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(nof_prb) (8 * nof_prb)
#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))
@ -54,13 +53,12 @@
/** 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
cf_t* pilots[2][SRSLTE_NOF_SF_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_t *q,
uint32_t max_prb);
@ -69,39 +67,29 @@ SRSLTE_API int srslte_refsignal_cs_set_cell(srslte_refsignal_t * q,
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,
cf_t *pilots,
cf_t *sf_symbols);
SRSLTE_API int
srslte_refsignal_cs_put_sf(srslte_refsignal_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id, cf_t* sf_symbols);
SRSLTE_API int srslte_refsignal_cs_get_sf(srslte_cell_t cell,
uint32_t port_id,
cf_t *sf_symbols,
cf_t *pilots);
SRSLTE_API int srslte_refsignal_cs_get_sf(
srslte_refsignal_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id, cf_t* sf_symbols, cf_t* pilots);
SRSLTE_API uint32_t srslte_refsignal_cs_fidx(srslte_cell_t cell,
uint32_t l,
uint32_t port_id,
uint32_t m);
SRSLTE_API uint32_t srslte_refsignal_cs_fidx(srslte_cell_t cell, uint32_t l, uint32_t port_id, uint32_t m);
SRSLTE_API uint32_t srslte_refsignal_cs_nsymbol(uint32_t l,
srslte_cp_t cp,
uint32_t port_id);
SRSLTE_API uint32_t srslte_refsignal_cs_v(uint32_t port_id,
uint32_t ref_symbol_idx);
SRSLTE_API uint32_t srslte_refsignal_cs_v(uint32_t port_id, uint32_t ref_symbol_idx);
SRSLTE_API uint32_t srslte_refsignal_cs_nof_symbols(srslte_refsignal_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id);
SRSLTE_API uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id);
SRSLTE_API uint32_t srslte_refsignal_cs_nof_re(srslte_refsignal_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id);
SRSLTE_API int srslte_refsignal_mbsfn_init(srslte_refsignal_t *q, uint32_t max_prb);
SRSLTE_API int srslte_refsignal_mbsfn_set_cell(srslte_refsignal_t * q,
srslte_cell_t cell, uint16_t mbsfn_area_id);
SRSLTE_API int srslte_refsignal_mbsfn_set_cell(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 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);

@ -36,8 +36,9 @@
#define SRSLTE_REFSIGNAL_UL_H
#include "srslte/config.h"
#include "srslte/phy/phch/pucch.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/phch/pucch_cfg.h"
#include "srslte/phy/phch/pusch_cfg.h"
#define SRSLTE_NOF_GROUPS_U 30
#define SRSLTE_NOF_SEQUENCES_U 2
@ -54,11 +55,12 @@ typedef struct SRSLTE_API {
bool sequence_hopping_en;
} srslte_refsignal_dmrs_pusch_cfg_t;
typedef struct SRSLTE_API {
// Common Configuration
uint32_t subframe_config;
uint32_t bw_cfg;
bool simul_ack;
// Dedicated configuration
uint32_t B;
@ -73,12 +75,10 @@ typedef struct SRSLTE_API {
/** Uplink DeModulation Reference Signal (DMRS) */
typedef struct SRSLTE_API {
srslte_cell_t cell;
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
srslte_pucch_cfg_t pucch_cfg;
srslte_refsignal_srs_cfg_t srs_cfg;
uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB];
float* tmp_arg;
uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB];
uint32_t n_prs_pusch[SRSLTE_NOF_DELTA_SS][SRSLTE_NSLOTS_X_FRAME]; // We precompute n_prs needed for cyclic shift alpha at srslte_refsignal_dl_init()
uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME];
uint32_t u_pucch[SRSLTE_NSLOTS_X_FRAME];
@ -86,11 +86,11 @@ typedef struct SRSLTE_API {
} srslte_refsignal_ul_t;
typedef struct {
cf_t **r[SRSLTE_NOF_CSHIFT][SRSLTE_NSUBFRAMES_X_FRAME];
cf_t** r[SRSLTE_NOF_CSHIFT][SRSLTE_NOF_SF_X_FRAME];
} srslte_refsignal_ul_dmrs_pregen_t;
typedef struct {
cf_t *r[SRSLTE_NSUBFRAMES_X_FRAME];
cf_t* r[SRSLTE_NOF_SF_X_FRAME];
} srslte_refsignal_srs_pregen_t;
SRSLTE_API int srslte_refsignal_ul_init(srslte_refsignal_ul_t *q,
@ -101,112 +101,95 @@ SRSLTE_API int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t *q,
SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q);
SRSLTE_API 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,
srslte_refsignal_srs_cfg_t *srs_cfg);
SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float *arg,
uint32_t u);
SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float* arg, uint32_t u);
SRSLTE_API uint32_t srslte_refsignal_dmrs_N_rs(srslte_pucch_format_t format,
srslte_cp_t cp);
SRSLTE_API uint32_t srslte_refsignal_dmrs_N_rs(srslte_pucch_format_t format, srslte_cp_t cp);
SRSLTE_API uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m,
srslte_pucch_format_t format,
srslte_cp_t cp);
SRSLTE_API uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp);
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);
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_init(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_refsignal_ul_dmrs_pregen_t* pregen,
srslte_refsignal_dmrs_pusch_cfg_t* cfg);
SRSLTE_API void srslte_refsignal_dmrs_pusch_pregen_free(srslte_refsignal_ul_t* q,
srslte_refsignal_ul_dmrs_pregen_t* pregen);
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen_put(srslte_refsignal_ul_t* q,
srslte_ul_sf_cfg_t* sf_cfg,
srslte_refsignal_ul_dmrs_pregen_t* pregen,
uint32_t nof_prb,
uint32_t sf_idx,
uint32_t cyclic_shift_for_dmrs,
uint32_t n_prb[2],
srslte_pusch_cfg_t* pusch_cfg,
cf_t* sf_symbols);
SRSLTE_API int srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t* q,
srslte_refsignal_dmrs_pusch_cfg_t* cfg,
uint32_t nof_prb,
uint32_t sf_idx,
uint32_t cyclic_shift_for_dmrs,
cf_t* r_pusch);
SRSLTE_API void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t* q,
srslte_pusch_cfg_t* pusch_cfg,
cf_t* r_pusch,
uint32_t nof_prb,
uint32_t n_prb[2],
cf_t* sf_symbols);
SRSLTE_API void srslte_refsignal_dmrs_pusch_get(srslte_refsignal_ul_t* q,
srslte_pusch_cfg_t* pusch_cfg,
cf_t* sf_symbols,
uint32_t nof_prb,
uint32_t n_prb[2],
cf_t* r_pusch);
SRSLTE_API int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t* q,
srslte_pucch_format_t format,
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
uint32_t sf_idx,
uint8_t pucch2_bits[2],
srslte_ul_sf_cfg_t* sf,
srslte_pucch_cfg_t* cfg,
cf_t* r_pucch);
SRSLTE_API int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q,
srslte_pucch_format_t format,
uint32_t n_pucch,
cf_t *r_pucch,
cf_t *output);
SRSLTE_API int
srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q, srslte_pucch_cfg_t* cfg, cf_t* r_pucch, cf_t* output);
SRSLTE_API int srslte_refsignal_dmrs_pucch_get(srslte_refsignal_ul_t* q,
srslte_pucch_format_t format,
uint32_t n_pucch,
cf_t *input,
cf_t *r_pucch);
SRSLTE_API int
srslte_refsignal_dmrs_pucch_get(srslte_refsignal_ul_t* q, srslte_pucch_cfg_t* cfg, cf_t* input, cf_t* r_pucch);
SRSLTE_API int srslte_refsignal_srs_pregen(srslte_refsignal_ul_t* q,
srslte_refsignal_srs_pregen_t *pregen);
srslte_refsignal_srs_pregen_t* pregen,
srslte_refsignal_srs_cfg_t* cfg,
srslte_refsignal_dmrs_pusch_cfg_t* dmrs);
SRSLTE_API int srslte_refsignal_srs_pregen_put(srslte_refsignal_ul_t* q,
srslte_refsignal_srs_pregen_t* pregen,
srslte_refsignal_srs_cfg_t* cfg,
uint32_t tti,
cf_t* sf_symbols);
SRSLTE_API void srslte_refsignal_srs_pregen_free(srslte_refsignal_ul_t *q,
srslte_refsignal_srs_pregen_t *pregen);
SRSLTE_API void srslte_refsignal_srs_pregen_free(srslte_refsignal_ul_t* q, srslte_refsignal_srs_pregen_t* pregen);
SRSLTE_API int srslte_refsignal_srs_gen(srslte_refsignal_ul_t* q,
srslte_refsignal_srs_cfg_t* cfg,
srslte_refsignal_dmrs_pusch_cfg_t* pusch_cfg,
uint32_t sf_idx,
cf_t* r_srs);
SRSLTE_API int srslte_refsignal_srs_put(srslte_refsignal_ul_t *q,
uint32_t tti,
cf_t *r_srs,
cf_t *sf_symbols);
SRSLTE_API int srslte_refsignal_srs_put(
srslte_refsignal_ul_t* q, srslte_refsignal_srs_cfg_t* cfg, uint32_t tti, cf_t* r_srs, cf_t* sf_symbols);
SRSLTE_API void srslte_refsignal_srs_pusch_shortened(srslte_refsignal_ul_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_refsignal_srs_cfg_t* srs_cfg,
srslte_pusch_cfg_t* pusch_cfg);
SRSLTE_API void srslte_refsignal_srs_pucch_shortened(srslte_refsignal_ul_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_refsignal_srs_cfg_t* srs_cfg,
srslte_pucch_cfg_t* pucch_cfg);
SRSLTE_API int srslte_refsignal_srs_send_cs(uint32_t subframe_config,
uint32_t sf_idx);
SRSLTE_API int srslte_refsignal_srs_send_cs(uint32_t subframe_config, uint32_t sf_idx);
SRSLTE_API int srslte_refsignal_srs_send_ue(uint32_t I_srs,
uint32_t tti);
SRSLTE_API int srslte_refsignal_srs_send_ue(uint32_t I_srs, uint32_t tti);
SRSLTE_API uint32_t srslte_refsignal_srs_rb_start_cs(uint32_t bw_cfg,
uint32_t nof_prb);
SRSLTE_API uint32_t srslte_refsignal_srs_rb_start_cs(uint32_t bw_cfg, uint32_t nof_prb);
SRSLTE_API uint32_t srslte_refsignal_srs_rb_L_cs(uint32_t bw_cfg,
uint32_t nof_prb);
SRSLTE_API uint32_t srslte_refsignal_srs_rb_L_cs(uint32_t bw_cfg, uint32_t nof_prb);
SRSLTE_API uint32_t srslte_refsignal_srs_M_sc(srslte_refsignal_ul_t *q);
SRSLTE_API uint32_t srslte_refsignal_srs_M_sc(srslte_refsignal_ul_t* q, srslte_refsignal_srs_cfg_t* cfg);
#endif // SRSLTE_REFSIGNAL_UL_H

@ -42,13 +42,15 @@
#include "srslte/config.h"
#define SRSLTE_NSUBFRAMES_X_FRAME 10
#define SRSLTE_NSLOTS_X_FRAME (2*SRSLTE_NSUBFRAMES_X_FRAME)
#define SRSLTE_NOF_SF_X_FRAME 10
#define SRSLTE_NSLOTS_X_FRAME (2 * SRSLTE_NOF_SF_X_FRAME)
#define SRSLTE_NSOFT_BITS 250368 // Soft buffer size for Category 1 UE
#define SRSLTE_PC_MAX 23 // Maximum TX power for Category 1 UE (in dBm)
#define SRSLTE_MAX_RADIOS 3 // Maximum number of supported RF devices
#define SRSLTE_MAX_CARRIERS 5 // Maximum number of supported simultaneous carriers
#define SRSLTE_MAX_PORTS 4
#define SRSLTE_MAX_LAYERS 4
#define SRSLTE_MAX_CODEWORDS 2
@ -66,9 +68,8 @@
#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;
typedef enum { SRSLTE_CP_NORM = 0, SRSLTE_CP_EXT } srslte_cp_t;
typedef enum { SRSLTE_SF_NORM = 0, SRSLTE_SF_MBSFN } srslte_sf_t;
#define SRSLTE_CRNTI_START 0x000B
#define SRSLTE_CRNTI_END 0xFFF3
@ -78,6 +79,13 @@ typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
#define SRSLTE_PRNTI 0xFFFE
#define SRSLTE_MRNTI 0xFFFD
#define SRSLTE_RNTI_ISRAR(rnti) (rnti >= SRSLTE_RARNTI_START && rnti <= SRSLTE_RARNTI_END)
#define SRSLTE_RNTI_ISUSER(rnti) (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END)
#define SRSLTE_RNTI_ISSI(rnti) (rnti == SRSLTE_SIRNTI)
#define SRSLTE_RNTI_ISPA(rnti) (rnti == SRSLTE_PRNTI)
#define SRSLTE_RNTI_ISMBSFN(rnti) (rnti == SRSLTE_MRNTI)
#define SRSLTE_RNTI_ISSIRAPA(rnti) (SRSLTE_RNTI_ISSI(rnti) || SRSLTE_RNTI_ISRAR(rnti) || SRSLTE_RNTI_ISPA(rnti))
#define SRSLTE_CELL_ID_UNKNOWN 1000
#define SRSLTE_MAX_NSYMB 7
@ -105,6 +113,9 @@ typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
#define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) (((symbol)==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN))
#define SRSLTE_CP_LEN_EXT(symbol_sz) (SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_EXT_LEN))
#define SRSLTE_CP_SZ(symbol_sz, cp) \
(SRSLTE_CP_LEN(symbol_sz, (SRSLTE_CP_ISNORM(cp) ? SRSLTE_CP_NORM_LEN : SRSLTE_CP_EXT_LEN)))
#define SRSLTE_SYMBOL_SZ(symbol_sz, cp) (symbol_sz + SRSLTE_CP_SZ(symbol_sz, cp))
#define SRSLTE_SLOT_LEN(symbol_sz) (symbol_sz * 15 / 2)
#define SRSLTE_SF_LEN(symbol_sz) (symbol_sz * 15)
#define SRSLTE_SF_LEN_MAX (SRSLTE_SF_LEN(SRSLTE_SYMBOL_SZ_MAX))
@ -114,6 +125,7 @@ typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
#define SRSLTE_SLOT_LEN_RE(nof_prb, cp) (nof_prb*SRSLTE_NRE*SRSLTE_CP_NSYMB(cp))
#define SRSLTE_SF_LEN_RE(nof_prb, cp) (2*SRSLTE_SLOT_LEN_RE(nof_prb, cp))
#define SRSLTE_NOF_RE(cell) (2 * SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp))
#define SRSLTE_TA_OFFSET (10e-6)
@ -133,20 +145,22 @@ typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
|| l == 0 \
|| l == SRSLTE_CP_NSYMB(cp) - 3)
#define SRSLTE_NOF_CTRL_SYMBOLS(cell, cfi) (cfi + (cell.nof_prb < 10 ? 1 : 0))
#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_FDD_NOF_HARQ (TX_DELAY + FDD_HARQ_DELAY_MS)
#define SRSLTE_MAX_HARQ_PROC 15
#define SRSLTE_NOF_LTE_BANDS 38
#define SRSLTE_NOF_LTE_BANDS 58
#define SRSLTE_DEFAULT_MAX_FRAMES_PBCH 500
#define SRSLTE_DEFAULT_MAX_FRAMES_PSS 10
#define SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES 10
#define ZERO_OBJECT(x) memset(&(x), 0x0, sizeof((x)))
typedef enum SRSLTE_API {
SRSLTE_PHICH_NORM = 0,
@ -158,49 +172,106 @@ typedef enum SRSLTE_API {
SRSLTE_PHICH_R_1_2,
SRSLTE_PHICH_R_1,
SRSLTE_PHICH_R_2
} srslte_phich_r_t;
} srslte_phich_resources_t;
typedef enum SRSLTE_API { SRSLTE_FDD = 0, SRSLTE_TDD = 1 } srslte_frame_type_t;
typedef enum {
SRSLTE_RNTI_USER = 0, /* Cell RNTI */
SRSLTE_RNTI_SI, /* System Information RNTI */
SRSLTE_RNTI_RAR, /* Random Access RNTI */
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;
typedef struct SRSLTE_API {
uint32_t sf_config;
uint32_t ss_config;
bool configured;
} srslte_tdd_config_t;
typedef enum SRSLTE_API {
SRSLTE_TDD_SF_D = 0,
SRSLTE_TDD_SF_U = 1,
SRSLTE_TDD_SF_S = 2,
} srslte_tdd_sf_t;
typedef struct {
uint8_t mbsfn_area_id;
uint8_t non_mbsfn_region_length;
uint8_t mbsfn_mcs;
bool enable;
bool is_mcch;
} srslte_mbsfn_cfg_t;
// Common cell constant properties that require object reconfiguration
typedef struct SRSLTE_API {
uint32_t nof_prb;
uint32_t nof_ports;
uint32_t id;
srslte_cp_t cp;
srslte_phich_length_t phich_length;
srslte_phich_resources_t phich_resources;
srslte_phich_r_t phich_resources;
srslte_frame_type_t frame_type;
} srslte_cell_t;
// Common downlink properties that may change every subframe
typedef struct SRSLTE_API {
srslte_tdd_config_t tdd_config;
uint32_t tti;
uint32_t cfi;
srslte_sf_t sf_type;
uint32_t non_mbsfn_region;
} srslte_dl_sf_cfg_t;
typedef struct SRSLTE_API {
srslte_tdd_config_t tdd_config;
uint32_t tti;
bool shortened;
} srslte_ul_sf_cfg_t;
typedef enum SRSLTE_API {
SRSLTE_MIMO_TYPE_SINGLE_ANTENNA,
SRSLTE_MIMO_TYPE_TX_DIVERSITY,
SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX,
SRSLTE_MIMO_TYPE_CDD
} srslte_mimo_type_t;
SRSLTE_TM1 = 0,
SRSLTE_TM2,
SRSLTE_TM3,
SRSLTE_TM4,
SRSLTE_TM5,
SRSLTE_TM6,
SRSLTE_TM7,
SRSLTE_TM8,
SRSLTE_TMINV // Invalid Transmission Mode
} srslte_tm_t;
typedef enum SRSLTE_API {
SRSLTE_MIMO_DECODER_ZF,
SRSLTE_MIMO_DECODER_MMSE
} srslte_mimo_decoder_t;
SRSLTE_TXSCHEME_PORT0,
SRSLTE_TXSCHEME_DIVERSITY,
SRSLTE_TXSCHEME_SPATIALMUX,
SRSLTE_TXSCHEME_CDD
} srslte_tx_scheme_t;
typedef enum SRSLTE_API { SRSLTE_MIMO_DECODER_ZF, SRSLTE_MIMO_DECODER_MMSE } srslte_mimo_decoder_t;
typedef enum SRSLTE_API {
SRSLTE_MOD_BPSK = 0,
SRSLTE_MOD_QPSK,
SRSLTE_MOD_16QAM,
SRSLTE_MOD_64QAM,
SRSLTE_MOD_LAST
} srslte_mod_t;
typedef enum {
SRSLTE_DCI_FORMAT0 = 0,
SRSLTE_DCI_FORMAT1,
SRSLTE_DCI_FORMAT1A,
SRSLTE_DCI_FORMAT1C,
SRSLTE_DCI_FORMAT1B,
SRSLTE_DCI_FORMAT1D,
SRSLTE_DCI_FORMAT2,
SRSLTE_DCI_FORMAT2A,
SRSLTE_DCI_FORMAT2B,
// SRSLTE_DCI_FORMAT3,
// SRSLTE_DCI_FORMAT3A,
SRSLTE_DCI_NOF_FORMATS
} srslte_dci_format_t;
typedef enum {
SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_NORMAL = 0, /* No cell selection no pucch3 */
SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS,
SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3,
SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_ERROR,
} srslte_ack_nack_feedback_mode_t;
typedef struct SRSLTE_API {
int id;
float fd;
@ -226,6 +297,18 @@ SRSLTE_API bool srslte_cellid_isvalid(uint32_t cell_id);
SRSLTE_API bool srslte_nofprb_isvalid(uint32_t nof_prb);
SRSLTE_API srslte_tdd_sf_t srslte_sfidx_tdd_type(srslte_tdd_config_t tdd_config, uint32_t sf_idx);
SRSLTE_API uint32_t srslte_tdd_nof_harq(srslte_tdd_config_t tdd_config);
SRSLTE_API uint32_t srslte_sfidx_tdd_nof_up(srslte_tdd_config_t tdd_config);
SRSLTE_API uint32_t srslte_sfidx_tdd_nof_gp(srslte_tdd_config_t tdd_config);
SRSLTE_API uint32_t srslte_sfidx_tdd_nof_dw(srslte_tdd_config_t tdd_config);
SRSLTE_API uint32_t srslte_sfidx_tdd_nof_dw_slot(srslte_tdd_config_t tdd_config, uint32_t slot, srslte_cp_t cp);
SRSLTE_API bool srslte_sfidx_isvalid(uint32_t sf_idx);
SRSLTE_API bool srslte_portid_isvalid(uint32_t port_id);
@ -276,6 +359,8 @@ SRSLTE_API uint32_t srslte_mod_bits_x_symbol(srslte_mod_t mod);
SRSLTE_API int srslte_band_get_band(uint32_t dl_earfcn);
SRSLTE_API bool srslte_band_is_tdd(uint32_t band);
SRSLTE_API float srslte_band_fd(uint32_t dl_earfcn);
SRSLTE_API float srslte_band_fu(uint32_t ul_earfcn);
@ -296,13 +381,13 @@ SRSLTE_API int srslte_band_get_fd_region(enum band_geographical_area region,
srslte_earfcn_t *earfcn,
uint32_t max_elems);
SRSLTE_API int srslte_str2mimotype(char *mimo_type_str,
srslte_mimo_type_t *type);
SRSLTE_API int srslte_str2mimotype(char* mimo_type_str, srslte_tx_scheme_t* type);
SRSLTE_API char *srslte_mimotype2str(srslte_mimo_type_t mimo_type);
SRSLTE_API char* srslte_mimotype2str(srslte_tx_scheme_t mimo_type);
/* Returns the interval tti1-tti2 mod 10240 */
SRSLTE_API uint32_t srslte_tti_interval(uint32_t tti1,
uint32_t tti2);
SRSLTE_API uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2);
SRSLTE_API uint32_t srslte_print_check(char* s, size_t max_len, uint32_t cur_len, const char* format, ...);
#endif // SRSLTE_PHY_COMMON_H

@ -40,11 +40,9 @@
#include <stdbool.h>
#include "srslte/phy/ch_estimation/refsignal_dl.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/sync/pss.h"
#include "srslte/phy/sync/sss.h"
#include "srslte/phy/ch_estimation/refsignal_dl.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/phch/pbch.h"
#include "srslte/phy/phch/pcfich.h"
@ -52,10 +50,14 @@
#include "srslte/phy/phch/pdsch.h"
#include "srslte/phy/phch/pdsch_cfg.h"
#include "srslte/phy/phch/phich.h"
#include "srslte/phy/phch/pmch.h"
#include "srslte/phy/phch/ra.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/sync/pss.h"
#include "srslte/phy/sync/sss.h"
#include "srslte/phy/enb/enb_ul.h"
#include "srslte/phy/ue/ue_dl.h"
#include "srslte/phy/utils/vector.h"
#include "srslte/phy/utils/debug.h"
@ -65,12 +67,13 @@
typedef struct SRSLTE_API {
srslte_cell_t cell;
srslte_dl_sf_cfg_t dl_sf;
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
cf_t *slot1_symbols[SRSLTE_MAX_PORTS];
srslte_ofdm_t ifft[SRSLTE_MAX_PORTS];
srslte_ofdm_t ifft_mbsfn;
srslte_pbch_t pbch;
srslte_pcfich_t pcfich;
srslte_regs_t regs;
@ -81,35 +84,14 @@ typedef struct SRSLTE_API {
srslte_refsignal_t csr_signal;
srslte_refsignal_t mbsfnr_signal;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_pdsch_cfg_t pmch_cfg;
srslte_ra_dl_dci_t dl_dci;
srslte_dci_format_t dci_format;
uint32_t cfi;
cf_t pss_signal[SRSLTE_PSS_LEN];
float sss_signal0[SRSLTE_SSS_LEN];
float sss_signal5[SRSLTE_SSS_LEN];
float tx_amp;
float rho_b;
uint8_t tmp[1024*128];
} srslte_enb_dl_t;
typedef struct {
uint16_t rnti;
srslte_dci_format_t dci_format;
srslte_ra_dl_dci_t grant;
srslte_dci_location_t location;
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_TB];
uint8_t *data[SRSLTE_MAX_TB];
} srslte_enb_dl_pdsch_t;
typedef struct {
uint16_t rnti;
uint8_t ack;
uint32_t n_prb_lowest;
uint32_t n_dmrs;
@ -125,92 +107,31 @@ SRSLTE_API void srslte_enb_dl_free(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_power_allocation(srslte_enb_dl_t *q,
float rho_a,
float rho_b);
SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t* q, uint16_t rnti);
SRSLTE_API void srslte_enb_dl_apply_power_allocation(srslte_enb_dl_t *q);
SRSLTE_API void srslte_enb_dl_rem_rnti(srslte_enb_dl_t* q, uint16_t rnti);
SRSLTE_API void srslte_enb_dl_prepare_power_allocation(srslte_enb_dl_t *q);
SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t* q, srslte_dl_sf_cfg_t* dl_sf);
SRSLTE_API void srslte_enb_dl_set_amp(srslte_enb_dl_t *q,
float amp);
SRSLTE_API void srslte_enb_dl_put_phich(srslte_enb_dl_t* q, srslte_phich_grant_t* grant, bool ack);
SRSLTE_API void srslte_enb_dl_set_non_mbsfn_region(srslte_enb_dl_t *q, uint8_t non_mbsfn_region);
SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t* q, srslte_dci_cfg_t* dci_cfg, srslte_dci_dl_t* dci_dl);
SRSLTE_API void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q);
SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t* q, srslte_dci_cfg_t* dci_cfg, srslte_dci_ul_t* dci_ul);
SRSLTE_API void srslte_enb_dl_put_sync(srslte_enb_dl_t *q,
uint32_t sf_idx);
SRSLTE_API int
srslte_enb_dl_put_pdsch(srslte_enb_dl_t* q, srslte_pdsch_cfg_t* pdsch, uint8_t* data[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API void srslte_enb_dl_put_refs(srslte_enb_dl_t *q,
uint32_t sf_idx);
SRSLTE_API int srslte_enb_dl_put_pmch(srslte_enb_dl_t* q, srslte_pmch_cfg_t* pmch_cfg, uint8_t* data);
SRSLTE_API void srslte_enb_dl_put_mib(srslte_enb_dl_t *q,
uint32_t tti);
SRSLTE_API void srslte_enb_dl_put_pcfich(srslte_enb_dl_t *q,
uint32_t sf_idx);
SRSLTE_API void srslte_enb_dl_put_phich(srslte_enb_dl_t *q,
uint8_t ack,
uint32_t n_prb_lowest,
uint32_t n_dmrs,
uint32_t sf_idx);
SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q,
uint32_t tti);
SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t* q);
SRSLTE_API void srslte_enb_dl_put_mbsfn_base(srslte_enb_dl_t *q,
uint32_t tti);
SRSLTE_API bool srslte_enb_dl_gen_cqi_periodic(
srslte_cell_t* cell, srslte_dl_cfg_t* dl_cfg, uint32_t tti, uint32_t ri, srslte_cqi_cfg_t* cqi_cfg);
SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q);
SRSLTE_API bool
srslte_enb_dl_gen_cqi_aperiodic(srslte_cell_t* cell, srslte_dl_cfg_t* dl_cfg, uint32_t ri, srslte_cqi_cfg_t* cqi_cfg);
SRSLTE_API void srslte_enb_dl_gen_signal_mbsfn(srslte_enb_dl_t *q);
SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q,
uint16_t rnti);
SRSLTE_API void srslte_enb_dl_rem_rnti(srslte_enb_dl_t *q,
uint16_t rnti);
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,
int rv_idx[SRSLTE_MAX_CODEWORDS],
uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type);
SRSLTE_API int srslte_enb_dl_put_pmch(srslte_enb_dl_t *q,
srslte_ra_dl_grant_t *grant,
srslte_softbuffer_tx_t *softbuffer,
uint32_t sf_idx,
uint8_t *data_mbms);
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);
SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q,
srslte_ra_ul_dci_t *grant,
srslte_dci_location_t location,
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);
SRSLTE_API void srslte_enb_dl_save_signal(srslte_enb_dl_t* q);
#endif // SRSLTE_ENB_DL_H

@ -40,10 +40,11 @@
#include <stdbool.h>
#include "srslte/phy/ch_estimation/chest_ul.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/ch_estimation/chest_ul.h"
#include "srslte/phy/phch/prach.h"
#include "srslte/phy/phch/pucch.h"
#include "srslte/phy/phch/pusch.h"
#include "srslte/phy/phch/pusch_cfg.h"
#include "srslte/phy/phch/ra.h"
@ -53,52 +54,19 @@
#include "srslte/config.h"
typedef struct {
uint32_t n_prb_lowest;
uint32_t n_dmrs;
} srslte_enb_ul_phich_info_t;
typedef struct {
bool uci_cfg_en;
bool srs_cfg_en;
srslte_uci_cfg_t uci_cfg;
srslte_refsignal_srs_cfg_t srs_cfg;
srslte_pucch_sched_t pucch_sched;
} srslte_enb_ul_user_t;
typedef struct SRSLTE_API {
srslte_cell_t cell;
cf_t* sf_symbols;
cf_t *ce;
srslte_chest_ul_res_t chest_res;
srslte_ofdm_t fft;
srslte_chest_ul_t chest;
srslte_pusch_t pusch;
srslte_pucch_t pucch;
srslte_prach_t prach;
srslte_pusch_cfg_t pusch_cfg;
srslte_pusch_hopping_cfg_t hopping_cfg;
// Configuration for each user
srslte_enb_ul_user_t **users;
} srslte_enb_ul_t;
typedef struct {
uint16_t rnti;
srslte_ra_ul_dci_t grant;
srslte_dci_location_t location;
uint32_t rv_idx;
uint32_t current_tx_nb;
uint8_t *data;
srslte_softbuffer_rx_t *softbuffer;
bool needs_pdcch;
} 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,
cf_t *in_buffer,
@ -106,12 +74,8 @@ SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
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_set_cell(srslte_enb_ul_t* q, srslte_cell_t cell, srslte_refsignal_dmrs_pusch_cfg_t* pusch_cfg);
SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q,
uint16_t rnti);
@ -119,38 +83,18 @@ SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q,
SRSLTE_API void srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q,
uint16_t rnti);
SRSLTE_API int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti,
srslte_uci_cfg_t *uci_cfg,
srslte_pucch_sched_t *pucch_sched,
srslte_refsignal_srs_cfg_t *srs_cfg);
SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q);
SRSLTE_API int srslte_enb_ul_get_pucch(srslte_enb_ul_t* q,
uint16_t rnti,
uint32_t pdcch_n_cce,
uint32_t sf_rx,
srslte_uci_data_t *uci_data);
srslte_ul_sf_cfg_t* ul_sf,
srslte_pucch_cfg_t* cfg,
srslte_pucch_res_t* res);
SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t* q,
srslte_ra_ul_grant_t *grant,
srslte_softbuffer_rx_t *softbuffer,
uint16_t rnti,
uint32_t rv_idx,
uint32_t current_tx_nb,
uint8_t *data,
srslte_cqi_value_t *cqi_value,
srslte_uci_data_t *uci_data,
uint32_t tti);
SRSLTE_API int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q,
uint32_t tti,
uint32_t freq_offset,
cf_t *signal,
uint32_t *indices,
float *offsets,
float *peak2avg);
srslte_ul_sf_cfg_t* ul_sf,
srslte_pusch_cfg_t* cfg,
srslte_pusch_res_t* res);
SRSLTE_API uint32_t srslte_enb_ul_get_pucch_prb_idx(srslte_cell_t* cell, srslte_pucch_cfg_t* cfg, uint32_t ns);
#endif // SRSLTE_ENB_UL_H

@ -142,7 +142,7 @@ void MAKE_CALL(run_tdec_iteration)(srslte_tdec_t * h, llr_t * input)
h->n_iter++;
} else {
fprintf(stderr, "Error CB index not set (call srslte_tdec_new_cb() first\n");
ERROR("Error CB index not set (call srslte_tdec_new_cb() first\n");
}
}

@ -62,8 +62,7 @@ SRSLTE_API int srslte_layermap_type(cf_t *d[SRSLTE_MAX_CODEWORDS],
int nof_cw,
int nof_layers,
int nof_symbols[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t type);
srslte_tx_scheme_t type);
/* Generates the vector of data symbols "d" based on the vector of layer-mapped symbols "x"
*/
@ -89,6 +88,6 @@ SRSLTE_API int srslte_layerdemap_type(cf_t *x[SRSLTE_MAX_LAYERS],
int nof_cw,
int nof_layer_symbols,
int nof_symbols[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t type);
srslte_tx_scheme_t type);
#endif // SRSLTE_LAYERMAP_H

@ -72,7 +72,7 @@ SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS],
int codebook_idx,
int nof_symbols,
float scaling,
srslte_mimo_type_t type);
srslte_tx_scheme_t type);
/* Estimates the vector "x" based on the received signal "y" and the channel estimates "h"
*/
@ -120,7 +120,7 @@ SRSLTE_API int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS],
int nof_layers,
int codebook_idx,
int nof_symbols,
srslte_mimo_type_t type,
srslte_tx_scheme_t type,
float scaling,
float noise_estimate);

@ -45,15 +45,29 @@
#define SRSLTE_PMI_MAX_BITS 4
#define SRSLTE_CQI_STR_MAX_CHAR 64
typedef enum {
SRSLTE_CQI_MODE_10,
SRSLTE_CQI_MODE_11,
SRSLTE_CQI_MODE_12,
SRSLTE_CQI_MODE_20,
SRSLTE_CQI_MODE_21,
SRSLTE_CQI_MODE_22,
SRSLTE_CQI_MODE_30,
SRSLTE_CQI_MODE_31,
SRSLTE_CQI_MODE_NA,
} srslte_cqi_report_mode_t;
typedef struct {
bool configured;
bool periodic_configured;
bool aperiodic_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;
} srslte_cqi_periodic_cfg_t;
srslte_cqi_report_mode_t periodic_mode;
srslte_cqi_report_mode_t aperiodic_mode;
} srslte_cqi_report_cfg_t;
/* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband
CQI reports (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and
@ -68,11 +82,6 @@ typedef struct SRSLTE_API {
uint8_t wideband_cqi_cw1; // if RI > 1 then 4-bit width otherwise 0-bit width
uint32_t subband_diff_cqi_cw1; // if RI > 1 then 2N-bit width otherwise 0-bit width
uint32_t pmi; // if RI > 1 then 2-bit width otherwise 1-bit width
uint32_t N;
bool ri_present;
bool pmi_present;
bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false
bool rank_is_not_one; // If rank > 1 then true otherwise false
} srslte_cqi_hl_subband_t;
/* Table 5.2.2.6.3-1: Fields for channel quality information feedback for UE selected subband CQI
@ -83,7 +92,6 @@ typedef struct SRSLTE_API {
uint8_t wideband_cqi; // 4-bit width
uint8_t subband_diff_cqi; // 2-bit width
uint32_t position_subband; // L-bit width
uint32_t L;
} srslte_cqi_ue_subband_t;
/* Table 5.2.3.3.1-1: Fields for channel quality information feedback for wideband CQI reports
@ -101,15 +109,11 @@ typedef struct SRSLTE_API {
uint8_t wideband_cqi; // 4-bit width
uint8_t spatial_diff_cqi; // If Rank==1 then it is 0-bit width otherwise it is 3-bit width
uint8_t pmi;
bool pmi_present;
bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false
bool rank_is_not_one; // If rank > 1 then true otherwise false
} srslte_cqi_format2_wideband_t;
typedef struct SRSLTE_API {
uint8_t subband_cqi; // 4-bit width
uint8_t subband_label; // 1- or 2-bit width
bool subband_label_2_bits; // false, label=1-bit, true label=2-bits
} srslte_cqi_format2_subband_t;
typedef enum {
@ -119,6 +123,19 @@ typedef enum {
SRSLTE_CQI_TYPE_SUBBAND_HL
} srslte_cqi_type_t;
typedef struct SRSLTE_API {
bool data_enable;
bool ri_present;
bool pmi_present;
bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false
bool rank_is_not_one; // If rank > 1 then true otherwise false
bool subband_label_2_bits; // false, label=1-bit, true label=2-ack_value
uint32_t L;
uint32_t N;
srslte_cqi_type_t type;
uint32_t ri_len;
} srslte_cqi_cfg_t;
typedef struct {
union {
srslte_cqi_format2_wideband_t wideband;
@ -126,60 +143,32 @@ typedef struct {
srslte_cqi_ue_subband_t subband_ue;
srslte_cqi_hl_subband_t subband_hl;
};
srslte_cqi_type_t type;
bool data_crc;
} srslte_cqi_value_t;
SRSLTE_API int srslte_cqi_size(srslte_cqi_cfg_t* cfg);
SRSLTE_API int srslte_cqi_size(srslte_cqi_value_t *value);
SRSLTE_API int srslte_cqi_value_pack(srslte_cqi_value_t *value,
uint8_t buff[SRSLTE_CQI_MAX_BITS]);
SRSLTE_API int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg,
uint8_t buff[SRSLTE_CQI_MAX_BITS]);
SRSLTE_API int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg,
uint8_t buff[SRSLTE_CQI_MAX_BITS]);
SRSLTE_API int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg,
uint8_t buff[SRSLTE_CQI_MAX_BITS]);
SRSLTE_API int srslte_cqi_value_pack(srslte_cqi_cfg_t* cfg, srslte_cqi_value_t* value, uint8_t* buff);
SRSLTE_API int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg,
uint8_t buff[SRSLTE_CQI_MAX_BITS]);
SRSLTE_API int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS],
SRSLTE_API int srslte_cqi_value_unpack(srslte_cqi_cfg_t* cfg,
uint8_t buff[SRSLTE_CQI_MAX_BITS],
srslte_cqi_value_t* value);
SRSLTE_API int srslte_cqi_value_tostring(srslte_cqi_value_t *value, char *buff, uint32_t buff_len);
SRSLTE_API int srslte_cqi_hl_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS],
srslte_cqi_hl_subband_t *msg);
SRSLTE_API int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS],
srslte_cqi_ue_subband_t *msg);
SRSLTE_API int srslte_cqi_value_tostring(srslte_cqi_cfg_t* cfg,
srslte_cqi_value_t* value,
char* buff,
uint32_t buff_len);
SRSLTE_API int srslte_cqi_format2_wideband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS],
srslte_cqi_format2_wideband_t *msg);
SRSLTE_API bool srslte_cqi_periodic_send(srslte_cqi_report_cfg_t* periodic_cfg,uint32_t tti, srslte_frame_type_t frame_type);
SRSLTE_API int srslte_cqi_format2_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS],
srslte_cqi_format2_subband_t *msg);
SRSLTE_API bool srslte_cqi_periodic_ri_send(srslte_cqi_report_cfg_t* periodic_cfg,
uint32_t tti,
srslte_frame_type_t frame_type);
SRSLTE_API bool srslte_cqi_send(uint32_t I_cqi_pmi,
uint32_t tti);
SRSLTE_API bool srslte_ri_send(uint32_t I_cqi_pmi,
uint32_t I_ri,
uint32_t tti);
SRSLTE_API int srslte_cqi_hl_get_no_subbands(int nof_prb);
SRSLTE_API uint8_t srslte_cqi_from_snr(float snr);
SRSLTE_API float srslte_cqi_to_coderate(uint32_t cqi);
SRSLTE_API int srslte_cqi_hl_get_subband_size(int num_prbs);
SRSLTE_API int srslte_cqi_hl_get_no_subbands(int num_prbs);
SRSLTE_API void srslte_cqi_to_str(const uint8_t *cqi_value, int cqi_len, char *str, int str_len);
#endif // SRSLTE_CQI_H

@ -44,42 +44,22 @@
#include "srslte/phy/phch/ra.h"
#define SRSLTE_DCI_MAX_BITS 128
#define SRSLTE_RAR_GRANT_LEN 20
SRSLTE_API extern int harq_pid_len;
typedef enum {
SRSLTE_DCI_FORMAT0 = 0,
SRSLTE_DCI_FORMAT1,
SRSLTE_DCI_FORMAT1A,
SRSLTE_DCI_FORMAT1C,
SRSLTE_DCI_FORMAT1B,
SRSLTE_DCI_FORMAT1D,
SRSLTE_DCI_FORMAT2,
SRSLTE_DCI_FORMAT2A,
SRSLTE_DCI_FORMAT2B,
//SRSLTE_DCI_FORMAT3,
//SRSLTE_DCI_FORMAT3A,
SRSLTE_DCI_NOF_FORMATS
} srslte_dci_format_t;
// Each type is for a different interface to packing/unpacking functions
typedef struct SRSLTE_API {
enum {
SRSLTE_DCI_MSG_TYPE_PUSCH_SCHED,
SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED,
SRSLTE_DCI_MSG_TYPE_MCCH_CHANGE,
SRSLTE_DCI_MSG_TYPE_TPC_COMMAND,
SRSLTE_DCI_MSG_TYPE_RA_PROC_PDCCH
} type;
srslte_dci_format_t format;
}srslte_dci_msg_type_t;
typedef enum {
SRSLTE_DCI_SPEC_COMMON_ = 0,
SRSLTE_DCI_SPEC_UE = 1
} dci_spec_t;
#define SRSLTE_DCI_IS_TB_EN(tb) (!(tb.mcs_idx == 0 && tb.rv == 1))
#define SRSLTE_DCI_TB_DISABLE(tb) \
do { \
tb.mcs_idx = 0; \
tb.rv = 1; \
} while (0)
#define SRSLTE_DCI_HEXDEBUG 0
typedef struct {
bool multiple_csi_request_enabled;
bool cif_enabled;
bool srs_request_enabled;
bool ra_format_enabled;
} srslte_dci_cfg_t;
typedef struct SRSLTE_API {
uint32_t L; // Aggregation level
@ -87,11 +67,118 @@ typedef struct SRSLTE_API {
} srslte_dci_location_t;
typedef struct SRSLTE_API {
uint8_t data[SRSLTE_DCI_MAX_BITS];
uint8_t payload[SRSLTE_DCI_MAX_BITS];
uint32_t nof_bits;
srslte_dci_location_t location;
srslte_dci_format_t format;
uint16_t rnti;
} srslte_dci_msg_t;
typedef struct SRSLTE_API {
uint32_t mcs_idx;
int rv;
bool ndi;
uint32_t cw_idx;
} srslte_dci_tb_t;
typedef struct SRSLTE_API {
uint16_t rnti;
srslte_dci_format_t format;
srslte_dci_location_t location;
// Resource Allocation
srslte_ra_type_t alloc_type;
union {
srslte_ra_type0_t type0_alloc;
srslte_ra_type1_t type1_alloc;
srslte_ra_type2_t type2_alloc;
};
// Codeword information
srslte_dci_tb_t tb[SRSLTE_MAX_CODEWORDS];
bool tb_cw_swap;
uint32_t pinfo;
// Power control
bool pconf;
bool power_offset;
uint8_t tpc_pucch;
// RA order
bool is_ra_order;
uint32_t ra_preamble;
uint32_t ra_mask_idx;
// Release 10
uint32_t cif;
bool cif_present;
bool srs_request;
bool srs_request_present;
// Other parameters
uint32_t pid;
uint32_t dai;
bool is_tdd;
bool is_dwpts;
bool sram_id;
// For debugging purposes
#if SRSLTE_DCI_HEXDEBUG
uint32_t nof_bits;
char hex_str[SRSLTE_DCI_MAX_BITS];
#endif
} srslte_dci_dl_t;
/** Unpacked DCI Format0 message */
typedef struct SRSLTE_API {
uint16_t rnti;
srslte_dci_format_t format;
srslte_dci_location_t location;
srslte_ra_type2_t type2_alloc;
/* 36.213 Table 8.4-2: SRSLTE_RA_PUSCH_HOP_HALF is 0 for < 10 Mhz and 10 for > 10 Mhz.
* SRSLTE_RA_PUSCH_HOP_QUART is 00 for > 10 Mhz and SRSLTE_RA_PUSCH_HOP_QUART_NEG is 01 for > 10 Mhz.
*/
enum {
SRSLTE_RA_PUSCH_HOP_DISABLED = -1,
SRSLTE_RA_PUSCH_HOP_QUART = 0,
SRSLTE_RA_PUSCH_HOP_QUART_NEG = 1,
SRSLTE_RA_PUSCH_HOP_HALF = 2,
SRSLTE_RA_PUSCH_HOP_TYPE2 = 3
} freq_hop_fl;
// Codeword information
srslte_dci_tb_t tb;
uint32_t n_dmrs;
bool cqi_request;
// TDD parametres
uint32_t dai;
uint32_t ul_idx;
bool is_tdd;
// Power control
uint8_t tpc_pusch;
// Release 10
uint32_t cif;
bool cif_present;
bool multiple_csi_request_present;
uint32_t srs_request;
bool srs_request_present;
srslte_ra_type_t ra_type;
bool ra_type_present;
// For debugging purposes
#ifdef SRSLTE_DCI_HEXDEBUG
uint32_t nof_bits;
char hex_str[SRSLTE_DCI_MAX_BITS];
#endif
} srslte_dci_ul_t;
typedef struct SRSLTE_API {
uint32_t rba;
uint32_t trunc_mcs;
@ -101,96 +188,61 @@ typedef struct SRSLTE_API {
bool hopping_flag;
} srslte_dci_rar_grant_t;
/* Converts a received PDSCH DL scheduling DCI message
* to ra structures ready to be passed to the harq setup function
*/
SRSLTE_API int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg,
uint16_t msg_rnti,
uint32_t nof_prb,
uint32_t nof_ports,
srslte_ra_dl_dci_t *dl_dci,
srslte_ra_dl_grant_t *grant);
SRSLTE_API int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg,
uint32_t nof_prb,
uint32_t n_rb_ho,
srslte_ra_ul_dci_t *ul_dci,
srslte_ra_ul_grant_t *grant,
uint32_t harq_pid);
SRSLTE_API int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar,
uint32_t nof_prb,
uint32_t n_rb_ho,
srslte_ra_ul_dci_t *ul_dci,
srslte_ra_ul_grant_t *grant);
SRSLTE_API void srslte_dci_rar_grant_unpack(srslte_dci_rar_grant_t *rar,
uint8_t grant[SRSLTE_RAR_GRANT_LEN]);
SRSLTE_API void srslte_dci_rar_grant_pack(srslte_dci_rar_grant_t *rar,
uint8_t grant[SRSLTE_RAR_GRANT_LEN]);
SRSLTE_API void srslte_dci_rar_grant_fprint(FILE *stream,
srslte_dci_rar_grant_t *rar);
SRSLTE_API void srslte_dci_rar_unpack(uint8_t payload[SRSLTE_RAR_GRANT_LEN], srslte_dci_rar_grant_t* rar);
SRSLTE_API srslte_dci_format_t srslte_dci_format_from_string(char *str);
SRSLTE_API void srslte_dci_rar_pack(srslte_dci_rar_grant_t* rar, uint8_t payload[SRSLTE_RAR_GRANT_LEN]);
SRSLTE_API char* srslte_dci_format_string(srslte_dci_format_t format);
SRSLTE_API int srslte_dci_rar_to_ul_dci(srslte_cell_t* cell, srslte_dci_rar_grant_t* rar, srslte_dci_ul_t* dci_ul);
SRSLTE_API char* srslte_dci_format_string_short(srslte_dci_format_t format);
SRSLTE_API int srslte_dci_msg_pack_pusch(srslte_cell_t* cell,
srslte_dl_sf_cfg_t* sf,
srslte_dci_cfg_t* cfg,
srslte_dci_ul_t* dci,
srslte_dci_msg_t* msg);
SRSLTE_API int srslte_dci_location_set(srslte_dci_location_t *c,
uint32_t L,
uint32_t nCCE);
SRSLTE_API int srslte_dci_msg_unpack_pusch(srslte_cell_t* cell,
srslte_dl_sf_cfg_t* sf,
srslte_dci_cfg_t* cfg,
srslte_dci_msg_t* msg,
srslte_dci_ul_t* dci);
SRSLTE_API bool srslte_dci_location_isvalid(srslte_dci_location_t *c);
SRSLTE_API int srslte_dci_msg_pack_pdsch(srslte_cell_t* cell,
srslte_dl_sf_cfg_t* sf,
srslte_dci_cfg_t* cfg, srslte_dci_dl_t* dci, srslte_dci_msg_t* msg);
SRSLTE_API int srslte_dci_msg_get_type(srslte_dci_msg_t *msg,
srslte_dci_msg_type_t *type,
uint32_t nof_prb,
uint16_t msg_rnti);
SRSLTE_API int srslte_dci_msg_unpack_pdsch(srslte_cell_t* cell,
srslte_dl_sf_cfg_t* sf,
srslte_dci_cfg_t* cfg,
srslte_dci_msg_t* msg,
srslte_dci_dl_t* dci);
SRSLTE_API void srslte_dci_msg_type_fprint(FILE *f,
srslte_dci_msg_type_t type);
SRSLTE_API uint32_t srslte_dci_format_sizeof(srslte_cell_t* cell,
srslte_dl_sf_cfg_t* sf,
srslte_dci_cfg_t* cfg,
srslte_dci_format_t format);
// For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PUSCH_SCHED
SRSLTE_API int srslte_dci_msg_pack_pusch(srslte_ra_ul_dci_t *data,
srslte_dci_msg_t *msg,
SRSLTE_API void srslte_dci_dl_fprint(FILE* f,
srslte_dci_dl_t* dci,
uint32_t nof_prb);
SRSLTE_API int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg,
srslte_ra_ul_dci_t *data,
uint32_t nof_prb);
SRSLTE_API uint32_t srslte_dci_dl_info(srslte_dci_dl_t* dci_dl,
char* str,
uint32_t str_len);
// For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED
SRSLTE_API int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data,
srslte_dci_format_t format,
srslte_dci_msg_t *msg,
uint32_t nof_prb,
uint32_t nof_ports,
bool crc_is_crnti);
SRSLTE_API int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg,
srslte_ra_dl_dci_t *data,
uint32_t nof_prb,
uint32_t nof_ports,
bool crc_is_crnti);
SRSLTE_API uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format,
uint32_t nof_prb,
uint32_t nof_ports);
SRSLTE_API uint32_t srslte_dci_dl_info(char *info_str,
uint32_t str_len,
srslte_ra_dl_dci_t *dci_msg,
srslte_dci_format_t format);
SRSLTE_API uint32_t srslte_dci_ul_info(srslte_dci_ul_t* dci_ul,
char* info_str,
uint32_t len);
SRSLTE_API uint32_t srslte_dci_ul_info(char *info_str,
uint32_t len,
srslte_ra_ul_dci_t *dci_msg);
SRSLTE_API srslte_dci_format_t srslte_dci_format_from_string(char* str);
// This is for backwards compatibility only for tm1 formats
SRSLTE_API uint32_t srslte_dci_format_sizeof_lut(srslte_dci_format_t format,
uint32_t nof_prb);
SRSLTE_API char* srslte_dci_format_string(srslte_dci_format_t format);
SRSLTE_API char* srslte_dci_format_string_short(srslte_dci_format_t format);
SRSLTE_API int srslte_dci_location_set(srslte_dci_location_t* c,
uint32_t L,
uint32_t nCCE);
SRSLTE_API bool srslte_dci_location_isvalid(srslte_dci_location_t* c);
#endif // DCI_

@ -38,16 +38,17 @@
#define SRSLTE_PBCH_H
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/chest_dl.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/fec/convcoder.h"
#include "srslte/phy/fec/crc.h"
#include "srslte/phy/fec/rm_conv.h"
#include "srslte/phy/fec/viterbi.h"
#include "srslte/phy/mimo/layermap.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/scrambling/scrambling.h"
#include "srslte/phy/fec/rm_conv.h"
#include "srslte/phy/fec/convcoder.h"
#include "srslte/phy/fec/viterbi.h"
#include "srslte/phy/fec/crc.h"
#define SRSLTE_BCH_PAYLOAD_LEN 24
#define SRSLTE_BCH_PAYLOADCRC_LEN (SRSLTE_BCH_PAYLOAD_LEN+16)
@ -93,26 +94,21 @@ 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,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN],
uint32_t* nof_tx_ports,
int* sfn_offset);
SRSLTE_API int srslte_pbch_encode(srslte_pbch_t* q,
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN],
cf_t *slot1_symbols[SRSLTE_MAX_PORTS],
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
uint32_t frame_idx);
SRSLTE_API void srslte_pbch_decode_reset(srslte_pbch_t *q);
SRSLTE_API void srslte_pbch_mib_unpack(uint8_t *msg,
srslte_cell_t *cell,
uint32_t *sfn);
SRSLTE_API void srslte_pbch_mib_unpack(uint8_t* msg, srslte_cell_t* cell, uint32_t* sfn);
SRSLTE_API void srslte_pbch_mib_pack(srslte_cell_t *cell,
uint32_t sfn,
uint8_t *msg);
SRSLTE_API void srslte_pbch_mib_pack(srslte_cell_t* cell, uint32_t sfn, uint8_t* msg);
#endif // SRSLTE_PBCH_H

@ -36,13 +36,14 @@
#define SRSLTE_PCFICH_H
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/chest_dl.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/mimo/precoding.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/scrambling/scrambling.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/scrambling/scrambling.h"
#define PCFICH_CFI_LEN 32
#define PCFICH_RE PCFICH_CFI_LEN/2
@ -74,7 +75,7 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq[SRSLTE_NOF_SF_X_FRAME];
} srslte_pcfich_t;
@ -88,24 +89,11 @@ SRSLTE_API int srslte_pcfich_set_cell(srslte_pcfich_t *q,
SRSLTE_API void srslte_pcfich_free(srslte_pcfich_t *q);
SRSLTE_API int srslte_pcfich_decode(srslte_pcfich_t* q,
cf_t *sf_symbols,
cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate,
uint32_t subframe,
uint32_t *cfi,
float *corr_result);
SRSLTE_API int srslte_pcfich_decode_multi(srslte_pcfich_t *q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate,
uint32_t subframe,
uint32_t *cfi,
float* corr_result);
SRSLTE_API int srslte_pcfich_encode(srslte_pcfich_t *q,
uint32_t cfi,
cf_t *sf_symbols[SRSLTE_MAX_PORTS],
uint32_t subframe);
SRSLTE_API int srslte_pcfich_encode(srslte_pcfich_t* q, srslte_dl_sf_cfg_t* sf, cf_t* sf_symbols[SRSLTE_MAX_PORTS]);
#endif // SRSLTE_PCFICH_H

@ -36,21 +36,19 @@
#define SRSLTE_PDCCH_H
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/chest_dl.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/fec/rm_conv.h"
#include "srslte/phy/fec/convcoder.h"
#include "srslte/phy/fec/viterbi.h"
#include "srslte/phy/fec/crc.h"
#include "srslte/phy/fec/rm_conv.h"
#include "srslte/phy/fec/viterbi.h"
#include "srslte/phy/mimo/layermap.h"
#include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/scrambling/scrambling.h"
typedef enum SRSLTE_API {
SEARCH_UE, SEARCH_COMMON
@ -79,7 +77,7 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq[SRSLTE_NOF_SF_X_FRAME];
srslte_viterbi_t decoder;
srslte_crc_t crc;
@ -96,43 +94,31 @@ 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);
SRSLTE_API void srslte_pdcch_set_regs(srslte_pdcch_t* q, srslte_regs_t* regs);
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t* q);
SRSLTE_API float srslte_pdcch_coderate(uint32_t nof_bits,
uint32_t l);
/* Encoding function */
SRSLTE_API int srslte_pdcch_encode(srslte_pdcch_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_dci_msg_t* msg,
srslte_dci_location_t location,
uint16_t rnti,
cf_t *sf_symbols[SRSLTE_MAX_PORTS],
uint32_t nsubframe,
uint32_t cfi);
cf_t* sf_symbols[SRSLTE_MAX_PORTS]);
/* Decoding functions: Extract the LLRs and save them in the srslte_pdcch_t object */
SRSLTE_API int srslte_pdcch_extract_llr(srslte_pdcch_t *q,
cf_t *sf_symbols,
cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate,
uint32_t nsubframe,
uint32_t cfi);
SRSLTE_API int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q,
cf_t *sf_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate,
uint32_t nsubframe,
uint32_t cfi);
SRSLTE_API int srslte_pdcch_extract_llr(srslte_pdcch_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS]);
/* Decoding functions: Try to decode a DCI message after calling srslte_pdcch_extract_llr */
SRSLTE_API int srslte_pdcch_decode_msg(srslte_pdcch_t* q,
srslte_dci_msg_t *msg,
srslte_dci_location_t *location,
srslte_dci_format_t format,
uint32_t cfi,
uint16_t *crc_rem);
srslte_dl_sf_cfg_t* sf,
srslte_dci_cfg_t* dci_cfg,
srslte_dci_msg_t* msg);
SRSLTE_API int srslte_pdcch_dci_decode(srslte_pdcch_t* q,
float* e,
@ -156,22 +142,21 @@ SRSLTE_API void srslte_pdcch_dci_encode_conv(srslte_pdcch_t *q,
/* Function for generation of UE-specific search space DCI locations */
SRSLTE_API uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_dci_location_t* locations,
uint32_t max_locations,
uint32_t nsubframe,
uint32_t cfi,
uint16_t rnti);
SRSLTE_API uint32_t srslte_pdcch_ue_locations_ncce(uint32_t nof_cce,
srslte_dci_location_t* c,
uint32_t max_candidates,
uint32_t nsubframe,
uint32_t sf_idx,
uint16_t rnti);
SRSLTE_API uint32_t srslte_pdcch_ue_locations_ncce_L(uint32_t nof_cce,
srslte_dci_location_t* c,
uint32_t max_candidates,
uint32_t nsubframe,
uint32_t sf_idx,
uint16_t rnti,
int L);
@ -185,5 +170,4 @@ SRSLTE_API uint32_t srslte_pdcch_common_locations_ncce(uint32_t nof_cce,
srslte_dci_location_t* c,
uint32_t max_candidates);
#endif // SRSLTE_PDCCH_H

@ -36,19 +36,20 @@
#define SRSLTE_PDSCH_H
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/chest_dl.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/mimo/precoding.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/scrambling/scrambling.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/phch/pdsch_cfg.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/phch/sch.h"
#include "srslte/phy/phch/pdsch_cfg.h"
#include "srslte/phy/scrambling/scrambling.h"
typedef struct {
srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NOF_SF_X_FRAME];
uint32_t cell_id;
bool sequence_generated;
} srslte_pdsch_user_t;
@ -58,8 +59,6 @@ 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;
@ -67,9 +66,6 @@ typedef struct SRSLTE_API {
bool llr_is_8bit;
/* Power allocation parameter 3GPP 36.213 Clause 5.2 Rho_b */
float rho_a;
/* buffers */
// void buffers are shared for tx and rx
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
@ -78,7 +74,6 @@ typedef struct SRSLTE_API {
cf_t *d[SRSLTE_MAX_CODEWORDS]; /* Modulated/Demodulated codewords */
void *e[SRSLTE_MAX_CODEWORDS];
bool csi_enabled;
float *csi[SRSLTE_MAX_CODEWORDS]; /* Channel Strengh Indicator */
/* tx & rx objects */
@ -95,6 +90,11 @@ typedef struct SRSLTE_API {
} srslte_pdsch_t;
typedef struct {
uint8_t* payload;
bool crc;
float avg_iterations_block;
} srslte_pdsch_res_t;
SRSLTE_API int srslte_pdsch_init_ue(srslte_pdsch_t *q,
uint32_t max_prb,
@ -105,75 +105,48 @@ SRSLTE_API int srslte_pdsch_init_enb(srslte_pdsch_t *q,
SRSLTE_API void srslte_pdsch_free(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_set_power_allocation(srslte_pdsch_t *q,
float rho_a);
/* These functions modify the state of the object and may take some time */
SRSLTE_API int srslte_pdsch_enable_coworker(srslte_pdsch_t* q);
SRSLTE_API int srslte_pdsch_enable_csi(srslte_pdsch_t *q,
bool enable);
SRSLTE_API int srslte_pdsch_set_cell(srslte_pdsch_t* q, srslte_cell_t cell);
SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q,
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
uint16_t rnti);
SRSLTE_API int srslte_pdsch_cfg(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_API 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);
SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti);
/* These functions do not modify the state and run in real-time */
SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_pdsch_cfg_t* cfg,
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS],
uint8_t* data[SRSLTE_MAX_CODEWORDS],
uint16_t rnti,
cf_t* sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_pdsch_cfg_t* cfg,
srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS],
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate,
uint16_t rnti,
uint8_t *data[SRSLTE_MAX_CODEWORDS],
bool acks[SRSLTE_MAX_CODEWORDS]);
srslte_pdsch_res_t data[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_pdsch_pmi_select(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg,
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]);
SRSLTE_API int srslte_pdsch_select_pmi(srslte_pdsch_t* q,
srslte_chest_dl_res_t* channel,
uint32_t nof_layers,
uint32_t* best_pmi,
float sinr[SRSLTE_MAX_CODEBOOKS]);
SRSLTE_API int srslte_pdsch_cn_compute(srslte_pdsch_t *q,
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
uint32_t nof_ce,
float *cn);
SRSLTE_API int srslte_pdsch_compute_cn(srslte_pdsch_t* q, srslte_chest_dl_res_t* channel, float* cn);
SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q,
uint32_t max_iter);
SRSLTE_API uint32_t srslte_pdsch_grant_rx_info(srslte_pdsch_grant_t* grant,
srslte_pdsch_res_t res[SRSLTE_MAX_CODEWORDS],
char* str,
uint32_t str_len);
SRSLTE_API float srslte_pdsch_last_noi(srslte_pdsch_t *q);
SRSLTE_API int srslte_pdsch_enable_coworker(srslte_pdsch_t *q);
SRSLTE_API uint32_t srslte_pdsch_rx_info(srslte_pdsch_cfg_t* cfg,
srslte_pdsch_res_t res[SRSLTE_MAX_CODEWORDS],
char* str,
uint32_t str_len);
SRSLTE_API uint32_t srslte_pdsch_last_noi_cw(srslte_pdsch_t *q,
uint32_t cw_idx);
SRSLTE_API uint32_t srslte_pdsch_tx_info(srslte_pdsch_cfg_t* cfg, char* str, uint32_t str_len);
#endif // SRSLTE_PDSCH_H

@ -39,24 +39,41 @@
#include "srslte/phy/fec/softbuffer.h"
#include "srslte/phy/fec/cbsegm.h"
/* 3GPP 36.213 Table 5.2-1: The cell-specific ratio rho_B / rho_A for 1, 2, or 4 cell specific antenna ports */
static const float pdsch_cfg_cell_specific_ratio_table[2][4] =
{ /* One antenna port */ {1.0f / 1.0f, 4.0f / 5.0f, 3.0f / 5.0f, 2.0f / 5.0f},
/* Two or more antenna port */ {5.0f / 4.0f, 1.0f / 1.0f, 3.0f / 4.0f, 1.0f / 2.0f}
};
typedef struct SRSLTE_API {
srslte_tx_scheme_t tx_scheme;
uint32_t pmi;
bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t nof_prb;
uint32_t nof_re;
uint32_t nof_symb_slot[2];
srslte_ra_tb_t tb[SRSLTE_MAX_CODEWORDS];
int last_tbs[SRSLTE_MAX_CODEWORDS];
uint32_t nof_tb;
uint32_t nof_layers;
} srslte_pdsch_grant_t;
typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm[SRSLTE_MAX_CODEWORDS];
srslte_ra_dl_grant_t grant;
srslte_ra_nbits_t nbits[SRSLTE_MAX_CODEWORDS];
uint32_t rv[SRSLTE_MAX_CODEWORDS];
uint32_t sf_idx;
uint32_t nof_layers;
uint32_t codebook_idx;
srslte_mimo_type_t mimo_type;
bool tb_cw_swap;
srslte_pdsch_grant_t grant;
uint16_t rnti;
uint32_t max_nof_iterations;
srslte_mimo_decoder_t decoder_type;
float p_a;
uint32_t p_b;
float rs_power;
bool power_scale;
bool csi_enable;
union {
srslte_softbuffer_tx_t* tx[SRSLTE_MAX_CODEWORDS];
srslte_softbuffer_rx_t* rx[SRSLTE_MAX_CODEWORDS];
} softbuffers;
bool meas_time_en;
uint32_t meas_time_value;
} srslte_pdsch_cfg_t;
#endif // SRSLTE_PDSCH_CFG_H

@ -35,16 +35,15 @@
#ifndef SRSLTE_PHICH_H
#define SRSLTE_PHICH_H
#include "regs.h"
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/chest_dl.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/mimo/precoding.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/scrambling/scrambling.h"
#include "regs.h"
#define SRSLTE_PHICH_NORM_NSEQUENCES 8
#define SRSLTE_PHICH_EXT_NSEQUENCES 4
@ -81,12 +80,27 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod;
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq[SRSLTE_NOF_SF_X_FRAME];
} srslte_phich_t;
SRSLTE_API int srslte_phich_init(srslte_phich_t *q,
uint32_t nof_rx_antennas);
typedef struct SRSLTE_API {
uint32_t ngroup;
uint32_t nseq;
} srslte_phich_resource_t;
typedef struct SRSLTE_API {
uint32_t n_prb_lowest;
uint32_t n_dmrs;
uint32_t I_phich;
} srslte_phich_grant_t;
typedef struct SRSLTE_API {
bool ack_value;
float distance;
} srslte_phich_res_t;
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);
@ -94,31 +108,24 @@ 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 void srslte_phich_set_regs(srslte_phich_t* q, srslte_regs_t* regs);
SRSLTE_API void srslte_phich_calc(srslte_phich_t* q, srslte_phich_grant_t* grant, srslte_phich_resource_t* n_phich);
SRSLTE_API int srslte_phich_decode(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_dl_sf_cfg_t* sf,
srslte_chest_dl_res_t* channel,
srslte_phich_resource_t n_phich,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
srslte_phich_res_t* result);
SRSLTE_API int srslte_phich_encode(srslte_phich_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_phich_resource_t n_phich,
uint8_t ack,
uint32_t ngroup,
uint32_t nseq,
uint32_t nsubframe,
cf_t *slot_symbols[SRSLTE_MAX_PORTS]);
cf_t* sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API void srslte_phich_reset(srslte_phich_t *q,
cf_t *slot_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API void srslte_phich_reset(srslte_phich_t* q, cf_t* slot_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API uint32_t srslte_phich_ngroups(srslte_phich_t* q);

@ -37,25 +37,24 @@
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/mimo/layermap.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/scrambling/scrambling.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/phch/pdsch.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/phch/sch.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/scrambling/scrambling.h"
#include "srslte/phy/phch/ra_dl.h"
typedef struct {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq[SRSLTE_NOF_SF_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_pdsch_cfg_t pdsch_cfg;
uint16_t area_id;
} srslte_pmch_cfg_t;
/* PMCH object */
@ -84,13 +83,7 @@ typedef struct SRSLTE_API {
} 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 int srslte_pmch_init(srslte_pmch_t* q, uint32_t max_prb, uint32_t nof_rx_antennas);
SRSLTE_API void srslte_pmch_free(srslte_pmch_t* q);
@ -100,53 +93,19 @@ 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 void srslte_configure_pmch(srslte_pmch_cfg_t* pmch_cfg, srslte_cell_t* cell, srslte_mbsfn_cfg_t* mbsfn_cfg);
SRSLTE_API int srslte_pmch_encode(srslte_pmch_t* q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
srslte_dl_sf_cfg_t* sf,
srslte_pmch_cfg_t* cfg,
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,
srslte_dl_sf_cfg_t* sf,
srslte_pmch_cfg_t* cfg,
srslte_chest_dl_res_t* channel,
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);
srslte_pdsch_res_t* data);
#endif // SRSLTE_PMCH_H

@ -100,6 +100,9 @@ typedef struct SRSLTE_API {
float peak_values[65];
uint32_t peak_offsets[65];
srslte_tdd_config_t tdd_config;
uint32_t current_prach_idx;
} srslte_prach_t;
typedef struct SRSLTE_API {
@ -118,8 +121,20 @@ typedef struct {
uint32_t zero_corr_zone;
uint32_t freq_offset;
bool hs_flag;
srslte_tdd_config_t tdd_config;
} srslte_prach_cfg_t;
typedef struct SRSLTE_API {
uint32_t f;
uint32_t t0;
uint32_t t1;
uint32_t t2;
} srslte_prach_tdd_loc_t;
typedef struct SRSLTE_API {
uint32_t nof_elems;
srslte_prach_tdd_loc_t elems[6];
} srslte_prach_tdd_loc_table_t;
SRSLTE_API uint32_t srslte_prach_get_preamble_format(uint32_t config_idx);
@ -129,31 +144,48 @@ SRSLTE_API bool srslte_prach_tti_opportunity(srslte_prach_t *p,
uint32_t current_tti,
int allowed_subframe);
SRSLTE_API bool srslte_prach_tti_opportunity_config(uint32_t config_idx,
SRSLTE_API bool srslte_prach_tti_opportunity_config_fdd(uint32_t config_idx,
uint32_t current_tti,
int allowed_subframe);
SRSLTE_API void srslte_prach_sf_config(uint32_t config_idx,
srslte_prach_sf_config_t *sf_config);
SRSLTE_API bool srslte_prach_tti_opportunity_config_tdd(uint32_t config_idx,
uint32_t tdd_ul_dl_config,
uint32_t current_tti,
uint32_t* prach_idx);
SRSLTE_API uint32_t srslte_prach_f_ra_tdd(uint32_t config_idx,
uint32_t tdd_ul_dl_config,
uint32_t current_tti,
uint32_t prach_idx,
uint32_t prach_offset,
uint32_t n_rb_ul);
SRSLTE_API uint32_t srslte_prach_f_id_tdd(uint32_t config_idx, uint32_t tdd_ul_dl_config, uint32_t prach_idx);
SRSLTE_API int srslte_prach_init(srslte_prach_t *p,
uint32_t max_N_ifft_ul);
SRSLTE_API uint32_t srslte_prach_nof_f_idx_tdd(uint32_t config_idx, uint32_t tdd_ul_dl_config);
SRSLTE_API int srslte_prach_set_cell(srslte_prach_t *p,
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 max_N_ifft_ul);
SRSLTE_API int srslte_prach_set_cell_fdd(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,
uint32_t nof_prb);
SRSLTE_API int srslte_prach_set_cell_tdd(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_tdd_config_t* tdd_config);
SRSLTE_API int srslte_prach_set_cfg(srslte_prach_t* p, srslte_prach_cfg_t* cfg, uint32_t nof_prb);
SRSLTE_API int srslte_prach_gen(srslte_prach_t *p,
uint32_t seq_index,
uint32_t freq_offset,
cf_t *signal);
SRSLTE_API int srslte_prach_gen(srslte_prach_t* p, uint32_t seq_index, uint32_t freq_offset, cf_t* signal);
SRSLTE_API int srslte_prach_detect(srslte_prach_t* p,
uint32_t freq_offset,
@ -171,8 +203,7 @@ SRSLTE_API int srslte_prach_detect_offset(srslte_prach_t *p,
float *peak_to_avg,
uint32_t *ind_len);
SRSLTE_API void srslte_prach_set_detect_factor(srslte_prach_t *p,
float factor);
SRSLTE_API void srslte_prach_set_detect_factor(srslte_prach_t *p, float factor);
SRSLTE_API int srslte_prach_free(srslte_prach_t *p);

@ -36,51 +36,22 @@
#define SRSLTE_PUCCH_H
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/chest_ul.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/phch/cqi.h"
#include "srslte/phy/phch/pucch_cfg.h"
#include "srslte/phy/phch/uci.h"
#define SRSLTE_PUCCH_N_SEQ 12
#define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B
#define SRSLTE_PUCCH3_NOF_BITS (4 * SRSLTE_NRE)
#define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS
#define SRSLTE_PUCCH_MAX_SYMBOLS 128
typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_1 = 0,
SRSLTE_PUCCH_FORMAT_1A,
SRSLTE_PUCCH_FORMAT_1B,
SRSLTE_PUCCH_FORMAT_2,
SRSLTE_PUCCH_FORMAT_2A,
SRSLTE_PUCCH_FORMAT_2B,
SRSLTE_PUCCH_FORMAT_ERROR,
} srslte_pucch_format_t;
typedef struct SRSLTE_API {
bool sps_enabled;
uint32_t tpc_for_pucch;
uint32_t N_pucch_1;
uint32_t n_pucch_1[4]; // 4 n_pucch resources specified by RRC
uint32_t n_pucch_2;
uint32_t n_pucch_sr;
}srslte_pucch_sched_t;
typedef struct SRSLTE_API {
// Common configuration
uint32_t delta_pucch_shift;
uint32_t n_rb_2;
uint32_t N_cs;
uint32_t n1_pucch_an;
// SRS configuration
bool srs_configured;
uint32_t srs_cs_subf_cfg;
bool srs_simul_ack;
} srslte_pucch_cfg_t;
typedef struct {
srslte_sequence_t seq_f2[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq_f2[SRSLTE_NOF_SF_X_FRAME];
uint32_t cell_id;
bool sequence_generated;
} srslte_pucch_user_t;
@ -88,12 +59,14 @@ typedef struct {
/* PUCCH object */
typedef struct SRSLTE_API {
srslte_cell_t cell;
srslte_pucch_cfg_t pucch_cfg;
srslte_modem_table_t mod;
srslte_uci_cqi_pucch_t cqi;
srslte_pucch_user_t** users;
srslte_sequence_t tmp_seq;
uint16_t ue_rnti;
bool is_ue;
uint8_t bits_scram[SRSLTE_PUCCH_MAX_BITS];
cf_t d[SRSLTE_PUCCH_MAX_BITS / 2];
@ -105,19 +78,13 @@ typedef struct SRSLTE_API {
cf_t *z_tmp;
cf_t *ce;
bool shortened;
bool group_hopping_en;
float threshold_format1;
float last_corr;
uint32_t last_n_prb;
uint32_t last_n_pucch;
srslte_sequence_t tmp_seq;
uint16_t ue_rnti;
bool is_ue;
} srslte_pucch_t;
typedef struct SRSLTE_API {
srslte_uci_value_t uci_data;
float correlation;
bool detected;
} srslte_pucch_res_t;
SRSLTE_API int srslte_pucch_init_ue(srslte_pucch_t *q);
@ -125,50 +92,32 @@ SRSLTE_API int srslte_pucch_init_enb(srslte_pucch_t *q);
SRSLTE_API void srslte_pucch_free(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);
SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q,
float format1_threshold);
SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q,
uint16_t c_rnti);
/* These functions modify the state of the object and may take some time */
SRSLTE_API int srslte_pucch_set_cell(srslte_pucch_t* q, srslte_cell_t cell);
SRSLTE_API void srslte_pucch_clear_rnti(srslte_pucch_t *q,
uint16_t rnti);
SRSLTE_API int srslte_pucch_set_rnti(srslte_pucch_t* q, uint16_t rnti);
SRSLTE_API uint32_t srslte_pucch_nof_symbols(srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format,
bool shortened);
SRSLTE_API void srslte_pucch_free_rnti(srslte_pucch_t* q, uint16_t rnti);
SRSLTE_API float srslte_pucch_get_last_corr(srslte_pucch_t* q);
/* These functions do not modify the state and run in real-time */
SRSLTE_API void srslte_pucch_uci_gen_cfg(srslte_pucch_t* q, srslte_pucch_cfg_t* cfg, srslte_uci_data_t* uci_data);
SRSLTE_API int srslte_pucch_encode(srslte_pucch_t* q,
srslte_pucch_format_t format,
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
uint32_t sf_idx,
uint16_t rnti,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS],
srslte_ul_sf_cfg_t* sf,
srslte_pucch_cfg_t* cfg,
srslte_uci_value_t* uci_data,
cf_t* sf_symbols);
SRSLTE_API int srslte_pucch_decode(srslte_pucch_t* q,
srslte_pucch_format_t format,
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
uint32_t sf_idx,
uint16_t rnti,
srslte_ul_sf_cfg_t* sf,
srslte_pucch_cfg_t* cfg,
srslte_chest_ul_res_t* channel,
cf_t* sf_symbols,
cf_t *ce,
float noise_estimate,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS],
uint32_t nof_bits);
srslte_pucch_res_t* data);
/* Other utilities. These functions do not modify the state and run in real-time */
SRSLTE_API float srslte_pucch_alpha_format1(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
srslte_pucch_cfg_t* cfg,
uint32_t n_pucch,
srslte_cp_t cp,
bool is_dmrs,
uint32_t ns,
@ -178,43 +127,32 @@ SRSLTE_API float srslte_pucch_alpha_format1(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_F
SRSLTE_API float srslte_pucch_alpha_format2(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
srslte_pucch_cfg_t* cfg,
uint32_t n_pucch,
uint32_t ns,
uint32_t l);
SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format,
uint32_t n_pucch,
srslte_cp_t cp);
SRSLTE_API int srslte_pucch_format2ab_mod_bits(srslte_pucch_format_t format, uint8_t bits[2], cf_t* d_10);
SRSLTE_API srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data,
srslte_cp_t cp);
SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t* cfg, srslte_cp_t cp);
SRSLTE_API uint32_t srslte_pucch_get_npucch(uint32_t n_cce,
srslte_pucch_format_t format,
bool has_scheduling_request,
srslte_pucch_sched_t *pucch_sched);
SRSLTE_API uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format,
uint32_t n_pucch,
uint32_t nof_prb,
srslte_cp_t cp,
uint32_t ns);
SRSLTE_API uint32_t srslte_pucch_n_prb(srslte_cell_t* cell, srslte_pucch_cfg_t* cfg, uint32_t ns);
SRSLTE_API int srslte_pucch_n_cs_cell(srslte_cell_t cell,
uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]);
SRSLTE_API int srslte_pucch_format2ab_mod_bits(srslte_pucch_format_t format,
uint8_t bits[2],
cf_t *d_10);
SRSLTE_API char* srslte_pucch_format_text(srslte_pucch_format_t format);
SRSLTE_API char* srslte_pucch_format_text_short(srslte_pucch_format_t format);
SRSLTE_API bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg,
uint32_t nof_prb);
SRSLTE_API void srslte_pucch_tx_info(srslte_pucch_cfg_t* cfg,
srslte_uci_value_t* uci_data,
char* str,
uint32_t str_len);
SRSLTE_API bool srslte_n_pucch_isvalid(srslte_pucch_t *q,
uint32_t n_pucch);
SRSLTE_API void srslte_pucch_rx_info(srslte_pucch_cfg_t* cfg,
srslte_uci_value_t* uci_data,
char* str,
uint32_t str_len);
SRSLTE_API void srslte_pucch_cfg_default(srslte_pucch_cfg_t *cfg);
SRSLTE_API bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t* cfg, uint32_t nof_prb);
#endif // SRSLTE_PUCCH_H

@ -0,0 +1,86 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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/.
*
*/
#ifndef SRSLTE_PUCCH_CFG_H
#define SRSLTE_PUCCH_CFG_H
#include "srslte/phy/phch/cqi.h"
#include "srslte/phy/phch/ra.h"
#include "srslte/phy/phch/uci_cfg.h"
#define SRSLTE_PUCCH_SIZE_AN_CS 4
#define SRSLTE_PUCCH_NOF_AN_CS 2
#define SRSLTE_PUCCH2_MAX_DMRS_BITS 16
typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_1 = 0,
SRSLTE_PUCCH_FORMAT_1A,
SRSLTE_PUCCH_FORMAT_1B,
SRSLTE_PUCCH_FORMAT_2,
SRSLTE_PUCCH_FORMAT_2A,
SRSLTE_PUCCH_FORMAT_2B,
SRSLTE_PUCCH_FORMAT_3,
SRSLTE_PUCCH_FORMAT_ERROR,
} srslte_pucch_format_t;
typedef struct SRSLTE_API {
// Input configuration for this subframe
uint16_t rnti;
// UCI configuration
srslte_uci_cfg_t uci_cfg;
// Common configuration
uint32_t delta_pucch_shift;
uint32_t n_rb_2;
uint32_t N_cs;
uint32_t N_pucch_1;
bool group_hopping_en; // common pusch config
// Dedicated PUCCH configuration
uint32_t I_sr;
bool sr_configured;
uint32_t n_pucch_1[4]; // 4 n_pucch resources specified by RRC
uint32_t n_pucch_2;
uint32_t n_pucch_sr;
bool simul_cqi_ack;
bool tdd_ack_bundle; // if false, multiplex
bool sps_enabled;
uint32_t tpc_for_pucch;
// Release 10 CA specific
srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode;
uint32_t n1_pucch_an_cs[SRSLTE_PUCCH_SIZE_AN_CS][SRSLTE_PUCCH_NOF_AN_CS];
uint32_t n3_pucch_an_list[SRSLTE_PUCCH_SIZE_AN_CS];
// Other configuration
float threshold_format1;
float threshold_data_valid_format1a;
float threshold_data_valid_format2;
// PUCCH configuration generated during a call to encode/decode
srslte_pucch_format_t format;
uint32_t n_pucch;
uint8_t pucch2_drs_bits[SRSLTE_PUCCH2_MAX_DMRS_BITS];
} srslte_pucch_cfg_t;
#endif // SRSLTE_PUCCH_CFG_H

@ -49,19 +49,8 @@
#include "srslte/phy/dft/dft_precoding.h"
#include "srslte/phy/ch_estimation/refsignal_ul.h"
#define SRSLTE_PUSCH_MAX_TDEC_ITERS 5
typedef struct {
enum {
SRSLTE_PUSCH_HOP_MODE_INTER_SF = 1,
SRSLTE_PUSCH_HOP_MODE_INTRA_SF = 0
} hop_mode;
uint32_t hopping_offset;
uint32_t n_sb;
} srslte_pusch_hopping_cfg_t;
typedef struct {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq[SRSLTE_NOF_SF_X_FRAME];
uint32_t cell_id;
bool sequence_generated;
} srslte_pusch_user_t;
@ -89,17 +78,25 @@ typedef struct SRSLTE_API {
/* tx & rx objects */
srslte_modem_table_t mod[4];
srslte_sequence_t seq_type2_fo;
srslte_sch_t ul_sch;
// This is to generate the scrambling seq for multiple CRNTIs
srslte_pusch_user_t **users;
srslte_sequence_t tmp_seq;
srslte_sch_t ul_sch;
bool shortened;
} srslte_pusch_t;
typedef struct SRSLTE_API {
uint8_t* ptr;
srslte_uci_value_t uci;
} srslte_pusch_data_t;
typedef struct SRSLTE_API {
uint8_t* data;
srslte_uci_value_t uci;
bool crc;
float avg_iterations_block;
} srslte_pusch_res_t;
SRSLTE_API int srslte_pusch_init_ue(srslte_pusch_t *q,
uint32_t max_prb);
@ -109,46 +106,40 @@ SRSLTE_API int srslte_pusch_init_enb(srslte_pusch_t *q,
SRSLTE_API void srslte_pusch_free(srslte_pusch_t *q);
/* These functions modify the state of the object and may take some time */
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,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg,
uint32_t tti,
uint32_t rv_idx,
uint32_t current_tx_nb);
SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q,
uint16_t rnti);
SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t* q, uint16_t rnti);
SRSLTE_API void srslte_pusch_free_rnti(srslte_pusch_t *q,
uint16_t rnti);
/* These functions do not modify the state and run in real-time */
SRSLTE_API int srslte_pusch_encode(srslte_pusch_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_pusch_cfg_t* cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
srslte_uci_data_t uci_data,
uint16_t rnti,
srslte_pusch_data_t* data,
cf_t* sf_symbols);
SRSLTE_API int srslte_pusch_decode(srslte_pusch_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_pusch_cfg_t* cfg,
srslte_softbuffer_rx_t *softbuffer,
srslte_chest_ul_res_t* channel,
cf_t* sf_symbols,
cf_t *ce,
float noise_estimate,
uint16_t rnti,
uint8_t *data,
srslte_cqi_value_t *cqi_value,
srslte_uci_data_t *uci_data);
srslte_pusch_res_t* data);
SRSLTE_API uint32_t srslte_pusch_grant_tx_info(srslte_pusch_grant_t* grant,
srslte_uci_cfg_t* uci_cfg,
srslte_uci_value_t* uci_data,
char* str,
uint32_t str_len);
SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q);
SRSLTE_API uint32_t srslte_pusch_tx_info(srslte_pusch_cfg_t* cfg,
srslte_uci_value_t* uci_data,
char* str,
uint32_t str_len);
SRSLTE_API uint32_t srslte_pusch_last_noi(srslte_pusch_t *q);
SRSLTE_API uint32_t srslte_pusch_rx_info(srslte_pusch_cfg_t* cfg, srslte_pusch_res_t* res, char* str, uint32_t str_len);
#endif // SRSLTE_PUSCH_H

@ -24,38 +24,66 @@
*
*/
/******************************************************************************
* File: pdsch_cfg.h
*
* Description: Physical downlink shared channel configuration
*
* Reference: 3GPP TS 36.211 version 10.0.0 Release 10 Sec. 6.4
*****************************************************************************/
#ifndef SRSLTE_PUSCH_CFG_H
#define SRSLTE_PUSCH_CFG_H
#include "srslte/phy/phch/ra.h"
#include "srslte/phy/fec/softbuffer.h"
#include "srslte/phy/fec/cbsegm.h"
#include "srslte/phy/phch/ra.h"
#include "srslte/phy/phch/uci_cfg.h"
typedef struct SRSLTE_API {
uint32_t I_offset_cqi;
uint32_t I_offset_ri;
uint32_t I_offset_ack;
} srslte_uci_cfg_t;
} srslte_uci_offset_cfg_t;
typedef struct {
enum { SRSLTE_PUSCH_HOP_MODE_INTER_SF = 1, SRSLTE_PUSCH_HOP_MODE_INTRA_SF = 0 } hop_mode;
uint32_t hopping_offset;
uint32_t n_sb;
uint32_t n_rb_ho;
uint32_t current_tx_nb;
bool hopping_enabled;
} srslte_pusch_hopping_cfg_t;
typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm;
srslte_ra_ul_grant_t grant;
srslte_ra_nbits_t nbits;
bool is_from_rar;
uint32_t L_prb;
uint32_t n_prb[2]; // rb_start after frequency hopping
uint32_t n_prb_tilde[2]; // rb_start after frequency hopping per retx
uint32_t freq_hopping;
uint32_t nof_re;
uint32_t nof_symb;
srslte_ra_tb_t tb;
srslte_ra_tb_t last_tb;
uint32_t n_dmrs;
} srslte_pusch_grant_t;
typedef struct SRSLTE_API {
uint16_t rnti;
srslte_uci_cfg_t uci_cfg;
uint32_t rv;
uint32_t sf_idx;
uint32_t tti;
srslte_cp_t cp;
srslte_uci_offset_cfg_t uci_offset;
srslte_pusch_grant_t grant;
uint32_t max_nof_iterations;
uint32_t last_O_cqi;
uint32_t K_segm;
uint32_t current_tx_nb;
bool csi_enable;
bool enable_64qam;
union {
srslte_softbuffer_tx_t* tx;
srslte_softbuffer_rx_t* rx;
} softbuffers;
bool meas_time_en;
uint32_t meas_time_value;
} srslte_pusch_cfg_t;
#endif // SRSLTE_PUSCH_CFG_H

@ -27,8 +27,7 @@
/******************************************************************************
* File: ra.h
*
* Description: Structures and utility functions for DL/UL resource allocation.
* Convert an UL/DL unpacket DCI message to a resource allocation
* Description: Implements Resource allocation Procedures common in for DL and UL
*
* Reference: 3GPP TS 36.213 version 10.0.1 Release 10
*****************************************************************************/
@ -49,17 +48,14 @@
typedef struct SRSLTE_API {
srslte_mod_t mod;
int tbs;
uint32_t idx;
} srslte_ra_mcs_t;
/* Structure that gives the number of encoded bits and RE for a UL/DL grant */
typedef struct {
uint32_t lstart;
uint32_t nof_symb;
int rv;
uint32_t nof_bits;
uint32_t nof_re;
} srslte_ra_nbits_t;
uint32_t cw_idx;
bool enabled;
// this is for debugging and metrics purposes
uint32_t mcs_idx;
} srslte_ra_tb_t;
typedef enum SRSLTE_API {
SRSLTE_RA_ALLOC_TYPE0 = 0,
@ -79,8 +75,6 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API {
uint32_t riv; // if L_crb==0, DCI message packer will take this value directly
uint32_t L_crb;
uint32_t RB_start;
enum {
SRSLTE_RA_TYPE2_NPRB1A_2 = 0, SRSLTE_RA_TYPE2_NPRB1A_3 = 1
} n_prb1a;
@ -92,181 +86,17 @@ typedef struct SRSLTE_API {
} mode;
} srslte_ra_type2_t;
SRSLTE_API uint32_t srslte_ra_type0_P(uint32_t nof_prb);
SRSLTE_API uint32_t srslte_ra_type2_n_vrb_dl(uint32_t nof_prb, bool ngap_is_1);
SRSLTE_API uint32_t srslte_ra_type2_n_rb_step(uint32_t nof_prb);
/**************************************************
* Structures used for Downlink Resource Allocation
**************************************************/
typedef struct SRSLTE_API {
bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t nof_prb;
uint32_t Qm[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
srslte_sf_t sf_type;
bool tb_en[SRSLTE_MAX_CODEWORDS];
uint32_t pinfo;
bool tb_cw_swap;
} 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 {
srslte_ra_type_t alloc_type;
union {
srslte_ra_type0_t type0_alloc;
srslte_ra_type1_t type1_alloc;
srslte_ra_type2_t type2_alloc;
};
uint32_t harq_process;
uint32_t mcs_idx;
int rv_idx;
bool ndi;
uint32_t mcs_idx_1;
int rv_idx_1;
bool ndi_1;
bool tb_cw_swap;
bool sram_id;
uint8_t pinfo;
bool pconf;
bool power_offset;
uint8_t tpc_pucch;
bool tb_en[2];
bool is_ra_order;
uint32_t ra_preamble;
uint32_t ra_mask_idx;
bool dci_is_1a;
bool dci_is_1c;
} srslte_ra_dl_dci_t;
/**************************************************
* Structures used for Uplink Resource Allocation
**************************************************/
typedef struct SRSLTE_API {
uint32_t n_prb[2];
uint32_t n_prb_tilde[2];
uint32_t L_prb;
uint32_t freq_hopping;
uint32_t M_sc;
uint32_t M_sc_init;
uint32_t Qm;
srslte_ra_mcs_t mcs;
uint32_t ncs_dmrs;
} srslte_ra_ul_grant_t;
/** Unpacked DCI Format0 message */
typedef struct SRSLTE_API {
/* 36.213 Table 8.4-2: SRSLTE_RA_PUSCH_HOP_HALF is 0 for < 10 Mhz and 10 for > 10 Mhz.
* SRSLTE_RA_PUSCH_HOP_QUART is 00 for > 10 Mhz and SRSLTE_RA_PUSCH_HOP_QUART_NEG is 01 for > 10 Mhz.
*/
enum {
SRSLTE_RA_PUSCH_HOP_DISABLED = -1,
SRSLTE_RA_PUSCH_HOP_QUART = 0,
SRSLTE_RA_PUSCH_HOP_QUART_NEG = 1,
SRSLTE_RA_PUSCH_HOP_HALF = 2,
SRSLTE_RA_PUSCH_HOP_TYPE2 = 3
} freq_hop_fl;
srslte_ra_ul_grant_t prb_alloc;
srslte_ra_type2_t type2_alloc;
uint32_t mcs_idx;
uint32_t rv_idx;
uint32_t n_dmrs;
bool ndi;
bool cqi_request;
uint8_t tpc_pusch;
} srslte_ra_ul_dci_t;
typedef union {
srslte_ra_ul_grant_t ul;
srslte_ra_dl_grant_t dl;
} srslte_phy_grant_t;
#define SRSLTE_PHY_GRANT_LEN sizeof(srslte_phy_grant_t)
/**************************************************
* Functions
**************************************************/
SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
uint32_t nof_prb,
uint16_t rnti,
srslte_ra_dl_grant_t *grant);
SRSLTE_API void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant,
uint32_t cfi,
srslte_cell_t cell,
uint32_t sf_idx,
srslte_ra_nbits_t nbits[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell,
uint32_t nof_prb,
uint32_t nof_ctrl_symbols);
SRSLTE_API 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);
SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci,
uint32_t nof_prb,
uint32_t n_rb_ho,
srslte_ra_ul_grant_t *grant);
SRSLTE_API void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant,
srslte_cp_t cp,
uint32_t N_srs,
srslte_ra_nbits_t *nbits);
SRSLTE_API int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci,
srslte_ra_ul_grant_t *grant,
uint32_t n_rb_ho,
uint32_t nof_prb);
SRSLTE_API int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci,
srslte_ra_dl_grant_t *grant,
uint32_t nof_prb);
SRSLTE_API int srslte_ra_dl_tbs_idx_from_mcs(uint32_t mcs);
SRSLTE_API int srslte_ra_ul_tbs_idx_from_mcs(uint32_t mcs);
SRSLTE_API srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs);
SRSLTE_API srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs);
SRSLTE_API int srslte_ra_dl_mcs_from_tbs_idx(uint32_t tbs_idx);
SRSLTE_API int srslte_ra_ul_mcs_from_tbs_idx(uint32_t tbs_idx);
SRSLTE_API int srslte_ra_tbs_from_idx(uint32_t tbs_idx,
uint32_t n_prb);
SRSLTE_API int srslte_ra_tbs_to_table_idx(uint32_t tbs,
uint32_t n_prb);
SRSLTE_API uint32_t srslte_ra_type2_ngap(uint32_t nof_prb, bool ngap_is_1);
SRSLTE_API uint32_t srslte_ra_type0_P(uint32_t nof_prb);
SRSLTE_API uint32_t srslte_ra_type1_N_rb(uint32_t nof_prb);
SRSLTE_API uint32_t srslte_ra_type2_to_riv(uint32_t L_crb,
uint32_t RB_start,
uint32_t nof_prb);
SRSLTE_API uint32_t srslte_ra_type2_to_riv(uint32_t L_crb, uint32_t RB_start, uint32_t nof_prb);
SRSLTE_API void srslte_ra_type2_from_riv(uint32_t riv,
uint32_t* L_crb,
@ -274,36 +104,16 @@ SRSLTE_API void srslte_ra_type2_from_riv(uint32_t riv,
uint32_t nof_prb,
uint32_t nof_vrb);
SRSLTE_API uint32_t srslte_ra_type2_n_vrb_dl(uint32_t nof_prb,
bool ngap_is_1);
SRSLTE_API int srslte_ra_tbs_idx_from_mcs(uint32_t mcs, bool is_ul);
SRSLTE_API uint32_t srslte_ra_type2_n_rb_step(uint32_t nof_prb);
SRSLTE_API uint32_t srslte_ra_type2_ngap(uint32_t nof_prb,
bool ngap_is_1);
SRSLTE_API uint32_t srslte_ra_type1_N_rb(uint32_t nof_prb);
SRSLTE_API void srslte_ra_pdsch_fprint(FILE *f,
srslte_ra_dl_dci_t *ra,
uint32_t nof_prb);
SRSLTE_API void srslte_ra_dl_grant_fprint(FILE *f,
srslte_ra_dl_grant_t *grant);
SRSLTE_API void srslte_ra_prb_fprint(FILE *f,
srslte_ra_dl_grant_t *grant);
SRSLTE_API void srslte_ra_pusch_fprint(FILE *f,
srslte_ra_ul_dci_t *ra,
uint32_t nof_prb);
SRSLTE_API srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs);
SRSLTE_API void srslte_ra_ul_grant_fprint(FILE *f,
srslte_ra_ul_grant_t *grant);
SRSLTE_API srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs);
SRSLTE_API int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb);
SRSLTE_API int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx, bool is_ul);
SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb);
SRSLTE_API int srslte_ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb);
SRSLTE_API int srslte_ra_tbs_to_table_idx(uint32_t tbs, uint32_t n_prb);
#endif // SRSLTE_RA_H

@ -0,0 +1,69 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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: ra_dl.h
*
* Description: Implements Resource allocation Procedures for DL defined in Section 7
*
* Reference: 3GPP TS 36.213 version 10.0.1 Release 10
*****************************************************************************/
#ifndef SRSLTE_RA_DL_H
#define SRSLTE_RA_DL_H
#include <stdbool.h>
#include <stdint.h>
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/phch/pdsch_cfg.h"
#include "srslte/phy/phch/ra.h"
/**************************************************
* Structures used for Downlink Resource Allocation
**************************************************/
/** Functions to generate a grant from a received DCI */
SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_cell_t* cell,
srslte_dl_sf_cfg_t* sf,
srslte_tm_t tm,
srslte_dci_dl_t* dci,
srslte_pdsch_grant_t* grant);
SRSLTE_API int srslte_ra_dl_grant_to_grant_prb_allocation(srslte_dci_dl_t* dci,
srslte_pdsch_grant_t* grant,
uint32_t nof_prb);
/** Functions used by the eNodeB scheduler */
SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t* cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols);
SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant);
/** Others */
SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb);
SRSLTE_API void srslte_ra_dl_compute_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant);
SRSLTE_API uint32_t srslte_ra_dl_info(srslte_pdsch_grant_t* grant, char* info_str, uint32_t len);
#endif // SRSLTE_RA_DL_H

@ -0,0 +1,67 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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: ra_ul.h
*
* Description: Implements Resource allocation Procedures for UL defined in Sections 8
*
* Reference: 3GPP TS 36.213 version 10.0.1 Release 10
*****************************************************************************/
#ifndef SRSLTE_RA_UL_H
#define SRSLTE_RA_UL_H
#include <stdbool.h>
#include <stdint.h>
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/phch/pusch_cfg.h"
// Structure for PUSCH frequency hopping procedure
typedef struct SRSLTE_API {
bool initialized;
srslte_cell_t cell;
srslte_sequence_t seq_type2_fo;
} srslte_ra_ul_pusch_hopping_t;
SRSLTE_API int srslte_ra_ul_pusch_hopping_init(srslte_ra_ul_pusch_hopping_t* q, srslte_cell_t cell);
SRSLTE_API void srslte_ra_ul_pusch_hopping_free(srslte_ra_ul_pusch_hopping_t* q);
SRSLTE_API void srslte_ra_ul_pusch_hopping(srslte_ra_ul_pusch_hopping_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_pusch_hopping_cfg_t* hopping_cfg,
srslte_pusch_grant_t* grant);
/** Functions to generate a grant from a received DCI */
SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_cell_t* cell,
srslte_ul_sf_cfg_t* sf,
srslte_pusch_hopping_cfg_t* hopping_cfg,
srslte_dci_ul_t* dci,
srslte_pusch_grant_t* grant);
/** Others */
SRSLTE_API uint32_t srslte_ra_ul_info(srslte_pusch_grant_t* grant, char* info_str, uint32_t len);
#endif // SRSLTE_RA_UL_H

@ -65,7 +65,7 @@ typedef struct SRSLTE_API {
uint32_t max_ctrl_symbols;
uint32_t ngroups_phich;
srslte_phich_resources_t phich_res;
srslte_phich_r_t phich_res;
srslte_phich_length_t phich_len;
srslte_regs_ch_t pcfich;
@ -73,6 +73,7 @@ typedef struct SRSLTE_API {
srslte_regs_ch_t pdcch[3]; /* PDCCH indexing, permutation and interleaving is computed for
the three possible CFI value */
uint32_t phich_mi;
uint32_t nof_regs;
srslte_regs_reg_t *regs;
}srslte_regs_t;
@ -80,8 +81,9 @@ typedef struct SRSLTE_API {
SRSLTE_API int srslte_regs_init(srslte_regs_t *h,
srslte_cell_t cell);
SRSLTE_API void srslte_regs_free(srslte_regs_t *h);
SRSLTE_API int srslte_regs_init_opts(srslte_regs_t* h, srslte_cell_t cell, uint32_t phich_mi, bool mbsfn_or_sf1_6_tdd);
SRSLTE_API void srslte_regs_free(srslte_regs_t* h);
SRSLTE_API int srslte_regs_pdcch_nregs(srslte_regs_t *h,
uint32_t cfi);
@ -98,6 +100,7 @@ SRSLTE_API int srslte_regs_pcfich_get(srslte_regs_t *h,
cf_t symbols[REGS_PCFICH_NSYM]);
SRSLTE_API uint32_t srslte_regs_phich_nregs(srslte_regs_t *h);
SRSLTE_API int srslte_regs_phich_add(srslte_regs_t *h,
cf_t symbols[REGS_PHICH_NSYM],
uint32_t ngroup,

@ -57,7 +57,7 @@
typedef struct SRSLTE_API {
uint32_t max_iterations;
uint32_t nof_iterations;
float avg_iterations;
bool llr_is_8bit;
@ -67,8 +67,7 @@ typedef struct SRSLTE_API {
void *e;
uint8_t *temp_g_bits;
uint32_t *ul_interleaver;
srslte_uci_bit_t ack_ri_bits[12*288];
uint32_t nof_ri_ack_bits;
srslte_uci_bit_t ack_ri_bits[57600]; // 4*M_sc*Qm_max for RI and ACK
srslte_tcod_t encoder;
srslte_tdec_t decoder;
@ -78,80 +77,47 @@ 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);
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 void srslte_sch_set_max_noi(srslte_sch_t *q,
uint32_t max_iterations);
SRSLTE_API float srslte_sch_last_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,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint8_t *e_bits);
SRSLTE_API int srslte_dlsch_encode(srslte_sch_t* q, srslte_pdsch_cfg_t* cfg, uint8_t* data, uint8_t* e_bits);
SRSLTE_API int srslte_dlsch_encode2(srslte_sch_t* q,
srslte_pdsch_cfg_t* cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t* data,
uint8_t* e_bits,
int codeword_idx);
int codeword_idx,
uint32_t nof_layers);
SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
int16_t *e_bits,
uint8_t *data);
SRSLTE_API int srslte_dlsch_decode(srslte_sch_t* q, srslte_pdsch_cfg_t* cfg, int16_t* e_bits, uint8_t* data);
SRSLTE_API int srslte_dlsch_decode2(srslte_sch_t* q,
srslte_pdsch_cfg_t* cfg,
srslte_softbuffer_rx_t *softbuffer,
int16_t* e_bits,
uint8_t* data,
int codeword_idx);
int codeword_idx,
uint32_t nof_layers);
SRSLTE_API int srslte_ulsch_encode(srslte_sch_t* q,
srslte_pusch_cfg_t* cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint8_t *g_bits,
uint8_t *q_bits);
SRSLTE_API int srslte_ulsch_uci_encode(srslte_sch_t *q,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t* data,
srslte_uci_data_t uci_data,
srslte_uci_value_t* uci_data,
uint8_t* g_bits,
uint8_t* q_bits);
SRSLTE_API int srslte_ulsch_decode(srslte_sch_t* q,
srslte_pusch_cfg_t* cfg,
srslte_softbuffer_rx_t *softbuffer,
int16_t* q_bits,
int16_t* g_bits,
uint8_t *data);
SRSLTE_API int srslte_ulsch_uci_decode(srslte_sch_t *q,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
int16_t *q_bits,
int16_t *g_bits,
uint8_t *data,
srslte_uci_data_t *uci_data);
SRSLTE_API int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
int16_t *q_bits,
uint8_t* c_seq,
srslte_uci_data_t *uci_data);
uint8_t* data,
srslte_uci_value_t* uci_data);
SRSLTE_API float srslte_sch_beta_cqi(uint32_t I_cqi);

@ -37,14 +37,15 @@
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/phch/pusch_cfg.h"
#include "srslte/phy/fec/crc.h"
#include "srslte/phy/fec/viterbi.h"
#include "srslte/phy/phch/cqi.h"
#include "srslte/phy/phch/pusch_cfg.h"
#include "srslte/phy/phch/uci_cfg.h"
#define SRSLTE_UCI_MAX_CQI_LEN_PUSCH 512
#define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13
#define SRSLTE_UCI_CQI_CODED_PUCCH_B 20
#define SRSLTE_UCI_STR_MAX_CHAR 32
typedef struct SRSLTE_API {
srslte_crc_t crc;
@ -61,29 +62,6 @@ typedef struct SRSLTE_API {
int16_t **cqi_table_s;
} srslte_uci_cqi_pucch_t;
typedef struct SRSLTE_API {
uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS];
uint32_t uci_cqi_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
uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK
uint32_t uci_ack_len;
bool ri_periodic_report;
bool scheduling_request;
bool channel_selection;
bool cqi_ack;
} srslte_uci_data_t;
typedef enum {
UCI_BIT_1 = 0, UCI_BIT_0, UCI_BIT_REPETITION, UCI_BIT_PLACEHOLDER
} srslte_uci_bit_type_t;
typedef struct {
uint32_t position;
srslte_uci_bit_type_t type;
} srslte_uci_bit_t;
SRSLTE_API void srslte_uci_cqi_pucch_init(srslte_uci_cqi_pucch_t *q);
SRSLTE_API void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q);
@ -98,10 +76,11 @@ SRSLTE_API int srslte_uci_encode_cqi_pucch_from_table(srslte_uci_cqi_pucch_t *q,
uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]);
SRSLTE_API int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t* q,
int16_t b_bits[32], // aligned for simd
int16_t b_bits[SRSLTE_CQI_MAX_BITS], // aligned for simd
uint8_t* cqi_data,
uint32_t cqi_len);
SRSLTE_API void srslte_uci_encode_ack_sr_pucch3(uint8_t* data, uint32_t nof_bits, uint8_t output[32]);
SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t* q);
@ -134,12 +113,13 @@ SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
SRSLTE_API int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t* cfg,
uint8_t* data,
uint32_t data_len,
uint32_t O_ack,
uint32_t O_cqi,
float beta,
uint32_t H_prime_total,
srslte_uci_bit_t *ri_bits,
bool is_ri);
bool input_is_ri,
uint32_t N_bundle,
srslte_uci_bit_t* ri_bits);
SRSLTE_API int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t* cfg,
int16_t* q_bits,
@ -152,5 +132,9 @@ SRSLTE_API int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg,
uint32_t nof_bits,
bool is_ri);
SRSLTE_API int srslte_uci_data_info(srslte_uci_cfg_t* uci_cfg,
srslte_uci_value_t* uci_data,
char* str,
uint32_t maxlen);
#endif // SRSLTE_UCI_H

@ -0,0 +1,71 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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/.
*
*/
#ifndef SRSLTE_UCI_CFG_H
#define SRSLTE_UCI_CFG_H
#include "srslte/phy/phch/cqi.h"
#define SRSLTE_UCI_MAX_ACK_BITS 10
#define SRSLTE_UCI_MAX_M 9
typedef struct SRSLTE_API {
uint8_t ack_value[SRSLTE_UCI_MAX_ACK_BITS];
bool valid;
} srslte_uci_value_ack_t;
typedef struct SRSLTE_API {
bool pending_tb[SRSLTE_MAX_CODEWORDS];
uint32_t nof_acks;
uint32_t ncce[SRSLTE_UCI_MAX_M];
uint32_t N_bundle;
uint32_t tdd_ack_M;
uint32_t tdd_ack_m;
bool tdd_is_bundling;
bool has_scell_ack;
} srslte_uci_cfg_ack_t;
typedef struct SRSLTE_API {
srslte_uci_cfg_ack_t ack;
srslte_cqi_cfg_t cqi;
bool is_scheduling_request_tti;
} srslte_uci_cfg_t;
typedef struct SRSLTE_API {
bool scheduling_request;
srslte_cqi_value_t cqi;
srslte_uci_value_ack_t ack;
uint8_t ri; // Only 1-bit supported for RI
} srslte_uci_value_t;
typedef struct SRSLTE_API {
srslte_uci_cfg_t cfg;
srslte_uci_value_t value;
} srslte_uci_data_t;
typedef enum { UCI_BIT_0 = 0, UCI_BIT_1 = 1, UCI_BIT_REPETITION = 2, UCI_BIT_PLACEHOLDER = 3 } srslte_uci_bit_type_t;
typedef struct {
uint32_t position;
srslte_uci_bit_type_t type;
} srslte_uci_bit_t;
#endif // SRSLTE_UCI_CFG_H

@ -129,8 +129,7 @@ SRSLTE_API void srslte_rf_suppress_stdout(srslte_rf_t *h);
SRSLTE_API void srslte_rf_register_error_handler(srslte_rf_t *h,
srslte_rf_error_handler_t error_handler);
SRSLTE_API double srslte_rf_set_rx_freq(srslte_rf_t *h,
double freq);
SRSLTE_API double srslte_rf_set_rx_freq(srslte_rf_t* h, uint32_t ch, double freq);
SRSLTE_API int srslte_rf_recv(srslte_rf_t *h,
void *data,
@ -157,12 +156,11 @@ SRSLTE_API double srslte_rf_set_tx_srate(srslte_rf_t *h,
SRSLTE_API double srslte_rf_set_tx_gain(srslte_rf_t *h,
double gain);
SRSLTE_API double srslte_rf_set_tx_freq(srslte_rf_t *h,
double freq);
SRSLTE_API double srslte_rf_set_tx_freq(srslte_rf_t* h, uint32_t ch, double freq);
SRSLTE_API void srslte_rf_get_time(srslte_rf_t *h,
time_t *secs,
double *frac_secs);
SRSLTE_API void srslte_rf_get_time(srslte_rf_t* h, time_t* secs, double* frac_secs);
SRSLTE_API int srslte_rf_sync(srslte_rf_t* rf);
SRSLTE_API int srslte_rf_send(srslte_rf_t *h,
void *data,

@ -35,6 +35,7 @@ typedef struct SRSLTE_API {
uint32_t max_frames_pss; // timeout in number of 5ms frames for synchronization
uint32_t nof_valid_pss_frames; // number of required synchronized frames
float init_agc; // 0 or negative to disable AGC
bool force_tdd;
} cell_search_cfg_t;
SRSLTE_API int rf_rssi_scan(srslte_rf_t *rf,

@ -104,8 +104,9 @@ SRSLTE_API void srslte_sss_put_slot(float *sss,
uint32_t nof_prb,
srslte_cp_t cp);
SRSLTE_API int srslte_sss_set_N_id_2(srslte_sss_t *q,
uint32_t N_id_2);
SRSLTE_API void srslte_sss_put_symbol(float* sss, cf_t* symbol, uint32_t nof_prb);
SRSLTE_API int srslte_sss_set_N_id_2(srslte_sss_t* q, uint32_t N_id_2);
SRSLTE_API int srslte_sss_m0m1_partial(srslte_sss_t *q,
const cf_t *input,

@ -91,6 +91,8 @@ typedef struct SRSLTE_API {
uint32_t max_frame_size;
srslte_frame_type_t frame_type;
bool detect_frame_type;
// variables for various CFO estimation methods
bool cfo_cp_enable;
@ -118,6 +120,13 @@ typedef struct SRSLTE_API {
cf_t sss_filt[SRSLTE_SYMBOL_SZ_MAX];
cf_t pss_filt[SRSLTE_SYMBOL_SZ_MAX];
bool sss_generated;
bool sss_detected;
bool sss_available;
srslte_dft_plan_t idftp_sss;
cf_t sss_recv[SRSLTE_SYMBOL_SZ_MAX];
cf_t sss_signal[2][SRSLTE_SYMBOL_SZ_MAX];
}srslte_sync_t;
typedef enum {
@ -182,6 +191,8 @@ SRSLTE_API void srslte_sync_set_em_alpha(srslte_sync_t *q,
SRSLTE_API int srslte_sync_set_N_id_2(srslte_sync_t *q,
uint32_t N_id_2);
SRSLTE_API int srslte_sync_set_N_id_1(srslte_sync_t* q, uint32_t N_id_1);
/* Gets the Physical CellId from the last call to synch_run() */
SRSLTE_API int srslte_sync_get_cell_id(srslte_sync_t *q);
@ -216,10 +227,10 @@ SRSLTE_API void srslte_sync_set_cfo_pss_enable(srslte_sync_t *q,
SRSLTE_API void srslte_sync_set_cfo_tol(srslte_sync_t *q,
float tol);
/* Sets the exponential moving average coefficient for CFO averaging */
SRSLTE_API void srslte_sync_set_cfo_ema_alpha(srslte_sync_t *q,
float alpha);
SRSLTE_API void srslte_sync_set_frame_type(srslte_sync_t* q, srslte_frame_type_t frame_type);
/* Sets the exponential moving average coefficient for CFO averaging */
SRSLTE_API void srslte_sync_set_cfo_ema_alpha(srslte_sync_t* q, float alpha);
/* Gets the CP length estimation from the last call to synch_run() */
SRSLTE_API srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q);
@ -236,9 +247,10 @@ SRSLTE_API srslte_pss_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q);
SRSLTE_API bool srslte_sync_sss_detected(srslte_sync_t *q);
SRSLTE_API bool srslte_sync_sss_available(srslte_sync_t* q);
/* Enables/Disables CP detection */
SRSLTE_API void srslte_sync_cp_en(srslte_sync_t *q,
bool enabled);
SRSLTE_API void srslte_sync_cp_en(srslte_sync_t* q, bool enabled);
#endif // SRSLTE_SYNC_H

@ -59,6 +59,7 @@
typedef struct SRSLTE_API {
uint32_t cell_id;
srslte_cp_t cp;
srslte_frame_type_t frame_type;
float peak;
float mode;
float psr;

@ -66,192 +66,182 @@
#define MAX_CANDIDATES_COM 6 // From 36.213 Table 9.1.1-1
#define MAX_CANDIDATES (MAX_CANDIDATES_UE + MAX_CANDIDATES_COM)
#define MI_NOF_REGS ((q->cell.frame_type == SRSLTE_FDD) ? 1 : 6)
#define MI_MAX_REGS 6
typedef struct {
#define SRSLTE_MAX_DCI_MSG SRSLTE_MAX_CARRIERS
typedef struct SRSLTE_API {
srslte_dci_format_t format;
srslte_dci_location_t loc[MAX_CANDIDATES];
uint32_t nof_locations;
} dci_blind_search_t;
typedef struct SRSLTE_API {
// Cell configuration
srslte_cell_t cell;
uint32_t nof_rx_antennas;
uint16_t current_mbsfn_area_id;
uint16_t pregen_rnti;
// Objects for all DL Physical Channels
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_MAX_PORTS];
srslte_ofdm_t fft_mbsfn;
srslte_chest_dl_t chest;
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;
// Control region
srslte_regs_t regs[MI_MAX_REGS];
uint32_t mi_manual_index;
bool mi_auto;
uint32_t nof_rx_antennas;
// Channel estimation and OFDM demodulation
srslte_chest_dl_t chest;
srslte_chest_dl_res_t chest_res;
srslte_ofdm_t fft[SRSLTE_MAX_PORTS];
srslte_ofdm_t fft_mbsfn;
cf_t *sf_symbols; // this is for backwards compatibility
cf_t *sf_symbols_m[SRSLTE_MAX_PORTS];
cf_t *ce[SRSLTE_MAX_PORTS]; // compatibility
cf_t *ce_m[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
/* RI, PMI and SINR for MIMO statistics */
float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS];
uint32_t pmi[SRSLTE_MAX_LAYERS];
uint32_t ri;
/* Power allocation parameter 3GPP 36.213 Clause 5.2 Rho_b */
float rho_b;
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;
srslte_dci_location_t last_location_ul;
// Buffers to store channel symbols after demodulation
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
srslte_dci_msg_t pending_ul_dci_msg;
uint16_t pending_ul_dci_rnti;
// Variables for blind DCI search
dci_blind_search_t current_ss_ue[MI_MAX_REGS][3][10];
dci_blind_search_t current_ss_common[MI_MAX_REGS][3];
srslte_dci_msg_t pending_ul_dci_msg[SRSLTE_MAX_DCI_MSG];
uint32_t pending_ul_dci_count;
float last_phich_corr;
} srslte_ue_dl_t;
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
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_set_cell(srslte_ue_dl_t *q,
srslte_cell_t cell);
int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint32_t *cfi);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint32_t *cfi,
srslte_sf_t sf_type);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate_noguru(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_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,
srslte_sf_t sf_type);
SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
srslte_ra_dl_grant_t *grant,
uint32_t cfi,
uint32_t sf_idx,
int rvidx[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type);
SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti,
srslte_dci_msg_t *dci_msg);
SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q,
uint32_t tm,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti,
srslte_dci_msg_t *dci_msg);
// Downlink config (includes common and dedicated variables)
typedef struct SRSLTE_API {
srslte_cqi_report_cfg_t cqi_report;
srslte_pdsch_cfg_t pdsch;
srslte_tm_t tm;
} srslte_dl_cfg_t;
SRSLTE_API int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q,
uint32_t tm,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti,
srslte_rnti_type_t rnti_type,
srslte_dci_msg_t *dci_msg);
typedef struct SRSLTE_API {
srslte_dl_cfg_t cfg;
srslte_chest_dl_cfg_t chest_cfg;
srslte_dci_cfg_t dci_cfg;
uint32_t last_ri;
float snr_to_cqi_offset;
} srslte_ue_dl_cfg_t;
SRSLTE_API uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q);
typedef struct {
uint32_t v_dai_dl;
uint32_t n_cce;
} srslte_pdsch_ack_resource_t;
SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t *q,
uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint32_t tm,
uint32_t tti,
bool acks[SRSLTE_MAX_CODEWORDS]);
typedef struct {
srslte_pdsch_ack_resource_t resource;
uint32_t k;
uint8_t value[SRSLTE_MAX_CODEWORDS]; // 0/1 or 2 for DTX
bool present;
} srslte_pdsch_ack_m_t;
SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q,
uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint32_t tm,
uint32_t tti,
uint16_t rnti,
bool acks[SRSLTE_MAX_CODEWORDS]);
typedef struct {
uint32_t M;
srslte_pdsch_ack_m_t m[SRSLTE_UCI_MAX_M];
} srslte_pdsch_ack_cc_t;
/* 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,
uint8_t *data,
uint32_t tti);
typedef struct {
srslte_pdsch_ack_cc_t cc[SRSLTE_MAX_CARRIERS];
uint32_t nof_cc;
uint32_t V_dai_ul;
srslte_tm_t transmission_mode;
srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode;
bool is_grant_available;
bool is_pusch_available;
bool tdd_ack_bundle;
bool simul_cqi_ack;
} srslte_pdsch_ack_t;
SRSLTE_API int
srslte_ue_dl_init(srslte_ue_dl_t* q, cf_t* input[SRSLTE_MAX_PORTS], 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_ri_pmi_select(srslte_ue_dl_t *q,
uint8_t *ri,
uint8_t *pmi,
float *current_sinr);
SRSLTE_API int srslte_ue_dl_set_cell(srslte_ue_dl_t* q, srslte_cell_t cell);
SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q,
uint8_t *ri,
float *cn);
SRSLTE_API void srslte_ue_dl_set_rnti(srslte_ue_dl_t* q, uint16_t rnti);
SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint32_t n_prb_lowest,
uint32_t n_dmrs);
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_reset(srslte_ue_dl_t *q);
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_set_rnti(srslte_ue_dl_t *q,
uint16_t rnti);
SRSLTE_API void srslte_ue_dl_set_mi_manual(srslte_ue_dl_t* q, uint32_t mi_idx);
/* 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_mi_auto(srslte_ue_dl_t* q);
SRSLTE_API void srslte_ue_dl_set_non_mbsfn_region(srslte_ue_dl_t *q,
uint8_t non_mbsfn_region_length);
/* Perform signal demodulation and channel estimation and store signals in the object */
SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, srslte_ue_dl_cfg_t* cfg);
SRSLTE_API void srslte_ue_dl_set_power_alloc(srslte_ue_dl_t *q,
float rho_a,
float rho_b);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate_noguru(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_ue_dl_cfg_t* cfg,
cf_t* input[SRSLTE_MAX_PORTS]);
/* Finds UL/DL DCI in the signal processed in a previous call to decode_fft_estimate() */
SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_ue_dl_cfg_t* cfg,
uint16_t rnti,
srslte_dci_ul_t dci_msg[SRSLTE_MAX_DCI_MSG]);
SRSLTE_API void srslte_ue_dl_save_signal(srslte_ue_dl_t *q,
srslte_softbuffer_rx_t *softbuffer,
uint32_t tti,
uint32_t rv_idx,
SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_ue_dl_cfg_t* cfg,
uint16_t rnti,
uint32_t cfi);
srslte_dci_dl_t dci_msg[SRSLTE_MAX_DCI_MSG]);
SRSLTE_API int srslte_ue_dl_dci_to_pdsch_grant(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_ue_dl_cfg_t* cfg,
srslte_dci_dl_t* dci,
srslte_pdsch_grant_t* grant);
/* Decodes PDSCH and PHICH in the signal processed in a previous call to decode_fft_estimate() */
SRSLTE_API int srslte_ue_dl_decode_pdsch(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_pdsch_cfg_t* pdsch_cfg,
srslte_pdsch_res_t data[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_ue_dl_decode_pmch(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_pmch_cfg_t* pmch_cfg,
srslte_pdsch_res_t* data);
SRSLTE_API int srslte_ue_dl_decode_phich(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_ue_dl_cfg_t* cfg,
srslte_phich_grant_t* grant,
srslte_phich_res_t* result);
SRSLTE_API int srslte_ue_dl_select_ri(srslte_ue_dl_t* q, uint32_t* ri, float* cn);
SRSLTE_API void srslte_ue_dl_gen_cqi_periodic(
srslte_ue_dl_t* q, srslte_ue_dl_cfg_t* cfg, uint32_t wideband_value, uint32_t tti, srslte_uci_data_t* uci_data);
SRSLTE_API void srslte_ue_dl_gen_cqi_aperiodic(srslte_ue_dl_t* q,
srslte_ue_dl_cfg_t* cfg,
uint32_t wideband_value,
srslte_uci_data_t* uci_data);
SRSLTE_API void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_pdsch_ack_t* ack_info,
srslte_uci_data_t* uci_data);
/* Functions used for testing purposes */
SRSLTE_API int srslte_ue_dl_find_and_decode(srslte_ue_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_ue_dl_cfg_t* cfg,
srslte_pdsch_cfg_t* pdsch_cfg,
uint8_t* data[SRSLTE_MAX_CODEWORDS],
bool acks[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API void srslte_ue_dl_save_signal(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, srslte_pdsch_cfg_t* pdsch_cfg);
#endif // SRSLTE_UE_DL_H

@ -64,13 +64,14 @@
typedef struct SRSLTE_API {
srslte_sync_t sfind;
cf_t *sf_symbols;
cf_t *ce[SRSLTE_MAX_PORTS];
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
srslte_ofdm_t fft;
srslte_chest_dl_t chest;
srslte_pbch_t pbch;
srslte_chest_dl_t chest;
srslte_chest_dl_res_t chest_res;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
uint32_t nof_tx_ports;
uint32_t sfn_offset;
@ -114,9 +115,7 @@ SRSLTE_API int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
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 int srslte_ue_mib_sync_set_cell(srslte_ue_mib_sync_t* q, srslte_cell_t cell);
SRSLTE_API void srslte_ue_mib_sync_reset(srslte_ue_mib_sync_t * q);

@ -70,7 +70,7 @@ public:
PDCCH_DL_SEARCH_SPS
} pdcch_dl_search_t;
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
/* Uplink/Downlink scheduling dci generated by a successfully decoded PDCCH */
class sched_grant {
public:
uint16_t get_rnti();
@ -81,8 +81,8 @@ public:
uint32_t get_harq_process();
private:
union {
srslte_ra_ul_dci_t ul_grant;
srslte_ra_dl_dci_t dl_grant;
srslte_ra_ul_grant_t ul_grant;
srslte_ra_dl_grant_t dl_grant;
};
direction_t dir;
};

@ -78,6 +78,8 @@ typedef enum SRSLTE_API { SF_FIND, SF_TRACK} srslte_ue_sync_state_t;
//#define MEASURE_EXEC_TIME
typedef int(ue_sync_recv_callback_t)(void*, cf_t * [SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*);
typedef struct SRSLTE_API {
srslte_sync_t sfind;
srslte_sync_t strack;
@ -122,8 +124,6 @@ typedef struct SRSLTE_API {
srslte_cell_t cell;
uint32_t sf_idx;
bool decode_sss_on_track;
bool cfo_is_copied;
bool cfo_correct_enable_track;
bool cfo_correct_enable_find;
@ -157,7 +157,8 @@ SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q,
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_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*),
@ -197,6 +198,12 @@ SRSLTE_API void srslte_ue_sync_cfo_reset(srslte_ue_sync_t *q);
SRSLTE_API void srslte_ue_sync_reset(srslte_ue_sync_t *q);
SRSLTE_API void srslte_ue_sync_set_frame_type(srslte_ue_sync_t* q, srslte_frame_type_t frame_type);
SRSLTE_API void srslte_ue_sync_set_nof_find_frames(srslte_ue_sync_t* q, uint32_t nof_frames);
SRSLTE_API srslte_frame_type_t srslte_ue_sync_get_frame_type(srslte_ue_sync_t* q);
SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t* q,
double(set_gain_callback)(void*, double),
double min_gain,
@ -209,14 +216,9 @@ SRSLTE_API void srslte_ue_sync_set_agc_period(srslte_ue_sync_t *q,
uint32_t period);
/* CAUTION: input_buffer MUST have space for 2 subframes */
SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q,
cf_t *input_buffer);
SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q,
cf_t *input_buffer[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_ue_sync_zerocopy(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_tol(srslte_ue_sync_t* q, float tol);
SRSLTE_API void srslte_ue_sync_copy_cfo(srslte_ue_sync_t *q,
srslte_ue_sync_t *src_obj);
@ -240,9 +242,6 @@ SRSLTE_API void srslte_ue_sync_set_cfo_i_enable(srslte_ue_sync_t *q,
SRSLTE_API void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q,
uint32_t N_id_2);
SRSLTE_API void srslte_ue_sync_decode_sss_on_track(srslte_ue_sync_t *q,
bool enabled);
SRSLTE_API uint32_t srslte_ue_sync_get_sfidx(srslte_ue_sync_t *q);
SRSLTE_API float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q);

@ -69,149 +69,88 @@ typedef struct {
} srslte_ue_ul_powerctrl_t;
typedef struct SRSLTE_API {
srslte_ofdm_t fft;
srslte_cfo_t cfo;
srslte_cell_t cell;
// Uplink config (includes common and dedicated variables)
srslte_pucch_cfg_t pucch;
srslte_pusch_cfg_t pusch;
srslte_pusch_hopping_cfg_t hopping;
srslte_ue_ul_powerctrl_t power_ctrl;
srslte_refsignal_dmrs_pusch_cfg_t dmrs;
srslte_refsignal_srs_cfg_t srs;
} srslte_ul_cfg_t;
typedef struct SRSLTE_API {
srslte_ul_cfg_t ul_cfg;
bool grant_available;
uint32_t cc_idx;
bool normalize_en;
bool cfo_en;
float cfo_tol;
float cfo_value;
} srslte_ue_ul_cfg_t;
typedef struct SRSLTE_API {
srslte_cell_t cell;
float current_cfo_tol;
float current_cfo;
srslte_pucch_format_t last_pucch_format;
uint16_t current_rnti;
bool signals_pregenerated;
srslte_ofdm_t fft;
srslte_cfo_t cfo;
srslte_pusch_cfg_t pusch_cfg;
srslte_refsignal_ul_t signals;
srslte_refsignal_ul_dmrs_pregen_t pregen_drms;
srslte_refsignal_ul_dmrs_pregen_t pregen_dmrs;
srslte_refsignal_srs_pregen_t pregen_srs;
srslte_softbuffer_tx_t softbuffer;
srslte_pusch_t pusch;
srslte_pucch_t pucch;
srslte_pucch_sched_t pucch_sched;
srslte_refsignal_srs_cfg_t srs_cfg;
srslte_uci_cfg_t uci_cfg;
srslte_pusch_hopping_cfg_t hopping_cfg;
srslte_ue_ul_powerctrl_t power_ctrl;
srslte_ra_ul_pusch_hopping_t hopping;
cf_t* out_buffer;
cf_t* refsignal;
cf_t* srs_signal;
cf_t* sf_symbols;
float last_amplitude;
uint16_t current_rnti;
bool signals_pregenerated;
} srslte_ue_ul_t;
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
cf_t *out_buffer,
uint32_t max_prb);
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t* q, cf_t* out_buffer, uint32_t max_prb);
SRSLTE_API void srslte_ue_ul_free(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,
bool enabled);
SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q,
bool enabled);
SRSLTE_API float srslte_ue_ul_get_last_amplitude(srslte_ue_ul_t *q);
SRSLTE_API void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg,
srslte_pucch_cfg_t *pucch_cfg,
srslte_pucch_sched_t *pucch_sched,
srslte_uci_cfg_t *uci_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_ue_ul_powerctrl_t *power_ctrl);
SRSLTE_API int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q,
srslte_ra_ul_grant_t *grant,
uint32_t tti,
uint32_t rvidx,
uint32_t current_tx_nb);
SRSLTE_API int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q,
srslte_uci_data_t uci_data,
uint32_t pdcch_n_cce, /* Ncce of the last PDCCH message received */
uint32_t tti,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q,
uint8_t *data,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q,
uint8_t *data,
uint16_t rnti,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q,
uint8_t *data,
srslte_uci_data_t uci_data,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_set_cell(srslte_ue_ul_t* q, srslte_cell_t cell);
SRSLTE_API int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q,
uint8_t *data,
srslte_uci_data_t uci_data,
uint16_t rnti,
cf_t *output_signal);
SRSLTE_API void srslte_ue_ul_set_rnti(srslte_ue_ul_t* q, uint16_t rnti);
SRSLTE_API int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q,
uint8_t *data,
srslte_uci_data_t uci_data,
srslte_softbuffer_tx_t *softbuffer,
uint16_t rnti,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pregen_signals(srslte_ue_ul_t* q, srslte_ue_ul_cfg_t* cfg);
SRSLTE_API int srslte_ue_ul_srs_encode(srslte_ue_ul_t *q,
uint32_t tti,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_dci_to_pusch_grant(srslte_ue_ul_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_ue_ul_cfg_t* cfg,
srslte_dci_ul_t* dci,
srslte_pusch_grant_t* grant);
SRSLTE_API void srslte_ue_ul_reset(srslte_ue_ul_t *q);
SRSLTE_API void srslte_ue_ul_pusch_hopping(srslte_ue_ul_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_ue_ul_cfg_t* cfg,
srslte_pusch_grant_t* grant);
SRSLTE_API int srslte_ue_ul_pregen_signals(srslte_ue_ul_t *q);
SRSLTE_API int
srslte_ue_ul_encode(srslte_ue_ul_t* q, srslte_ul_sf_cfg_t* sf, srslte_ue_ul_cfg_t* cfg, srslte_pusch_data_t* data);
SRSLTE_API void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q,
uint16_t rnti);
SRSLTE_API int srslte_ue_ul_sr_send_tti(srslte_pucch_cfg_t* cfg, uint32_t current_tti);
/* Power control procedure */
SRSLTE_API float srslte_ue_ul_pusch_power(srslte_ue_ul_t *q,
float PL,
float p0_preamble);
SRSLTE_API bool
srslte_ue_ul_gen_sr(srslte_ue_ul_cfg_t* cfg, srslte_ul_sf_cfg_t* sf, srslte_uci_data_t* uci_data, bool sr_request);
SRSLTE_API float srslte_ue_ul_pucch_power(srslte_ue_ul_t *q,
float PL,
srslte_pucch_format_t format,
uint32_t n_cqi,
uint32_t n_harq);
SRSLTE_API float srslte_ue_ul_srs_power(srslte_ue_ul_t *q,
float PL);
/* Other static functions for UL PHY procedures defined in 36.213 */
SRSLTE_API int srslte_ue_ul_sr_send_tti(uint32_t I_sr,
uint32_t current_tti);
SRSLTE_API bool srslte_ue_ul_srs_tx_enabled(srslte_refsignal_srs_cfg_t *srs_cfg,
uint32_t tti);
SRSLTE_API void srslte_ue_ul_pucch_resource_selection(srslte_cell_t* cell,
srslte_pucch_cfg_t* cfg,
srslte_uci_cfg_t* uci_cfg,
srslte_uci_value_t* uci_data);
SRSLTE_API bool srslte_ue_ul_info(
srslte_ue_ul_cfg_t* cfg, srslte_ul_sf_cfg_t* sf, srslte_uci_value_t* uci_data, char* str, uint32_t str_len);
#endif // SRSLTE_UE_UL_H

@ -35,9 +35,9 @@
#ifndef SRSLTE_DEBUG_H
#define SRSLTE_DEBUG_H
#include <stdio.h>
#include "phy_logger.h"
#include "srslte/config.h"
#include "srslte/phy/common/phy_logger.h"
#include <stdio.h>
#define SRSLTE_VERBOSE_DEBUG 2
#define SRSLTE_VERBOSE_INFO 1
@ -59,19 +59,34 @@ SRSLTE_API extern int handler_registered;
#define PRINT_INFO srslte_verbose=SRSLTE_VERBOSE_INFO
#define PRINT_NONE srslte_verbose=SRSLTE_VERBOSE_NONE
#define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered)\
{ fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__); }\
else{ srslte_phy_log_print(LOG_LEVEL_DEBUG, _fmt, ##__VA_ARGS__); }
#define DEBUG(_fmt, ...) \
do { \
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { \
fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__); \
} else { \
srslte_phy_log_print(LOG_LEVEL_DEBUG_S, _fmt, ##__VA_ARGS__); \
} \
} while (0)
#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) \
{ fprintf(stdout, "[INFO]: " _fmt, ##__VA_ARGS__); }\
else{ srslte_phy_log_print(LOG_LEVEL_INFO, _fmt, ##__VA_ARGS__); }
#define INFO(_fmt, ...) \
do { \
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { \
fprintf(stdout, "[INFO]: " _fmt, ##__VA_ARGS__); \
} else { \
srslte_phy_log_print(LOG_LEVEL_INFO_S, _fmt, ##__VA_ARGS__); \
} \
} while (0)
#if CMAKE_BUILD_TYPE==Debug
/* In debug mode, it prints out the */
#define ERROR(_fmt, ...) if (!handler_registered)\
{ fprintf(stderr, "\e[31m%s.%d: " _fmt "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__);}\
else {srslte_phy_log_print(LOG_LEVEL_ERROR, _fmt, ##__VA_ARGS__);} //
#define ERROR(_fmt, ...) \
do { \
if (!handler_registered) { \
fprintf(stderr, "\e[31m%s.%d: " _fmt "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__); \
} else { \
srslte_phy_log_print(LOG_LEVEL_ERROR_S, _fmt, ##__VA_ARGS__); \
} \
} while (0)
#else
#define ERROR(_fmt, ...) if (!handler_registered)\
{ fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__);}\

@ -1,19 +1,14 @@
/**
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* \section COPYRIGHT
* This file is part of srsLTE.
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* 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.
*
* srsUE is distributed in the hope that it will be useful,
* 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.
@ -39,12 +34,11 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef enum {LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR} phy_logger_level_t;
typedef enum { LOG_LEVEL_INFO_S, LOG_LEVEL_DEBUG_S, LOG_LEVEL_ERROR_S } phy_logger_level_t;
typedef void (*phy_log_handler_t)(phy_logger_level_t log_level, void* ctx, char* str);

@ -1,3 +1,23 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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/.
*
*/
#ifndef SRSLTE_RINGBUFFER_H
#define SRSLTE_RINGBUFFER_H

@ -26,13 +26,26 @@
#include <string.h>
#include "srslte/srslte.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/common/log_filter.h"
#include "srslte/common/trace.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/radio/radio_sync.h"
#include "srslte/srslte.h"
#ifndef SRSLTE_RADIO_H
#define SRSLTE_RADIO_H
typedef struct {
float tx_corr_dc_gain;
float tx_corr_dc_phase;
float tx_corr_iq_i;
float tx_corr_iq_q;
float rx_corr_dc_gain;
float rx_corr_dc_phase;
float rx_corr_iq_i;
float rx_corr_iq_q;
} rf_cal_t;
namespace srslte {
/* Interface to the RF frontend.
@ -46,6 +59,9 @@ class radio {
zeros = (cf_t*)srslte_vec_malloc(burst_preamble_max_samples * sizeof(cf_t));
bzero(zeros, burst_preamble_max_samples * sizeof(cf_t));
sync = NULL;
log_h = NULL;
burst_preamble_sec = 0;
is_start_of_burst = false;
burst_preamble_samples = 0;
@ -70,13 +86,18 @@ class radio {
{
if (zeros) {
free(zeros);
zeros = NULL;
}
}
bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1);
bool init(log_filter* _log_h,
char* args = NULL,
char* devname = NULL,
uint32_t nof_channels = 1,
bool enable_synch = false);
void stop();
void reset();
bool start_agc(bool tx_gain_same_rx);
bool start_agc(bool tx_gain_same_rx = false);
void set_burst_preamble(double preamble_us);
void set_tx_adv(int nsamples);
@ -86,11 +107,13 @@ class radio {
void set_continuous_tx(bool enable);
void get_time(srslte_timestamp_t *now);
bool tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
bool tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time);
int synch_wait();
void synch_issue();
bool tx_single(cf_t* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
bool tx(cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time);
void tx_end();
bool rx_now(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time);
bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time);
bool rx_now(cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t* rxd_time);
bool rx_at(cf_t* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time);
void set_tx_gain(float gain);
void set_rx_gain(float gain);
@ -98,8 +121,8 @@ class radio {
double set_rx_gain_th(float gain);
void set_freq_offset(double freq);
void set_tx_freq(double freq);
void set_rx_freq(double freq);
void set_tx_freq(uint32_t chan, double freq);
void set_rx_freq(uint32_t chan, double freq);
double get_freq_offset();
double get_tx_freq();
@ -118,9 +141,6 @@ class radio {
float get_rssi();
bool has_rssi();
void start_trace();
void write_trace(std::string filename);
void set_tti(uint32_t tti);
bool is_first_of_burst();
@ -131,9 +151,9 @@ class radio {
protected:
void save_trace(uint32_t is_eob, srslte_timestamp_t *usrp_time);
srslte_rf_t rf_device;
radio_sync* sync;
log_filter* log_h;
const static uint32_t burst_preamble_max_samples = 13824;
double burst_preamble_sec;// Start of burst preamble time (off->on RF transition time)

@ -42,13 +42,89 @@ namespace srslte {
/* Interface to the RF frontend.
*/
class radio_multi : public radio
class radio_multi
{
private:
/* Temporal buffer size for flushing the radios */
static const size_t TEMP_BUFFER_SIZE = 307200;
/* Maximum sample offset that can be compensated without isssuing PPS synchronism */
static const size_t MAX_NOF_ALIGN_SAMPLES = TEMP_BUFFER_SIZE * 10;
log_filter* log_h;
bool initiated;
double rx_srate;
std::vector<srslte::radio*> radios;
srslte_timestamp_t ts_rx[SRSLTE_MAX_RADIOS];
cf_t* temp_buffers[SRSLTE_MAX_RADIOS][SRSLTE_MAX_PORTS];
bool align_radio_ts();
bool synch_wait();
void synch_issue();
pthread_mutex_t mutex;
bool locked;
uint32_t nof_ports;
public:
radio_multi() {}
~radio_multi() {}
bool init_multi(uint32_t nof_rx_antennas, char *args = NULL, char *devname = NULL);
bool rx_now(cf_t *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time);
radio_multi();
bool init(log_filter* _log_h,
char* args[SRSLTE_MAX_RADIOS] = NULL,
char* devname = NULL,
uint32_t nof_radios = 1,
uint32_t nof_rf_ports = 1);
void stop();
void reset();
bool start_agc(bool tx_gain_same_rx = false);
void set_burst_preamble(double preamble_us);
void set_tx_adv(int nsamples);
void set_tx_adv_neg(bool tx_adv_is_neg);
void set_manual_calibration(rf_cal_t* calibration);
bool is_continuous_tx();
void set_continuous_tx(bool enable);
bool tx_single(cf_t* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
bool tx(cf_t* buffer[SRSLTE_MAX_RADIOS][SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time);
void tx_end();
bool rx_now(cf_t* buffer[SRSLTE_MAX_RADIOS][SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t* rxd_time);
void set_tx_gain(float gain, uint32_t radio_idx = UINT32_MAX);
void set_rx_gain(float gain, uint32_t radio_idx = UINT32_MAX);
void set_tx_rx_gain_offset(float offset);
double set_rx_gain_th(float gain);
float get_tx_gain(uint32_t radio_idx = 0);
float get_rx_gain(uint32_t radio_idx = 0);
void set_freq_offset(double freq);
void set_tx_freq(double freq, uint32_t radio_idx = UINT32_MAX);
void set_rx_freq(double freq, uint32_t radio_idx = UINT32_MAX);
double get_freq_offset();
double get_tx_freq(uint32_t radio_idx = 0);
double get_rx_freq(uint32_t radio_idx = 0);
srslte_rf_info_t* get_info(uint32_t radio_idx = 0);
void set_master_clock_rate(double rate);
void set_tx_srate(double srate);
void set_rx_srate(double srate);
float get_max_tx_power();
float set_tx_power(float power);
float get_rssi();
bool has_rssi();
radio* get_radio_ptr(uint32_t idx);
void start_trace();
void write_trace(std::string filename);
void set_tti(uint32_t tti);
bool is_init();
void register_error_handler(srslte_rf_error_handler_t h);
};
}

@ -0,0 +1,54 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* 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/.
*
*/
extern "C" {
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/common/timestamp.h"
#include "srslte/phy/rf/rf.h"
}
#ifndef SRSLTE_RADIO_SYNC_H
#define SRSLTE_RADIO_SYNC_H
namespace srslte {
/* Interface to the RF frontend.
*/
class radio_sync
{
private:
void* thread_args;
public:
radio_sync();
bool init(srslte_rf_t* dev);
void issue_sync();
void issue_rx(cf_t* data[SRSLTE_MAX_PORTS],
uint32_t nsamples,
srslte_timestamp_t* timestamp,
bool start_streaming = false);
int wait();
~radio_sync();
};
} // namespace srslte
#endif // SRSLTE_RADIO_SYNC_H

@ -47,10 +47,10 @@ extern "C" {
#include "srslte/phy/utils/cexptab.h"
#include "srslte/phy/utils/vector.h"
#include "srslte/phy/common/timestamp.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/common/phy_logger.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/common/timestamp.h"
#include "srslte/phy/utils/phy_logger.h"
#include "srslte/phy/ch_estimation/chest_ul.h"
#include "srslte/phy/ch_estimation/chest_dl.h"
@ -91,18 +91,20 @@ extern "C" {
#include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/mimo/layermap.h"
#include "srslte/phy/fec/softbuffer.h"
#include "srslte/phy/phch/cqi.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/fec/softbuffer.h"
#include "srslte/phy/phch/pbch.h"
#include "srslte/phy/phch/pcfich.h"
#include "srslte/phy/phch/pdcch.h"
#include "srslte/phy/phch/pdsch.h"
#include "srslte/phy/phch/phich.h"
#include "srslte/phy/phch/pusch.h"
#include "srslte/phy/phch/pucch.h"
#include "srslte/phy/phch/prach.h"
#include "srslte/phy/phch/pucch.h"
#include "srslte/phy/phch/pusch.h"
#include "srslte/phy/phch/ra.h"
#include "srslte/phy/phch/ra_dl.h"
#include "srslte/phy/phch/ra_ul.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/phch/sch.h"
#include "srslte/phy/phch/uci.h"

@ -150,7 +150,7 @@ public:
cfg.um.tx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS;
cfg.um.tx_mod = 32;
cfg.um.is_mrb = true;
cfg.tx_queue_length = 512;
cfg.tx_queue_length = 1024;
return cfg;
}
};

@ -145,6 +145,7 @@ void log_filter::console(const char * message, ...) {
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
printf("%s",args_msg); // Print directly to stdout
fflush(stdout);
va_end(args);
free(args_msg);
}

@ -63,7 +63,7 @@ void sch_pdu::parse_packet(uint8_t *ptr)
if (n_sub >= 0) {
subheaders[nof_subheaders-1].set_payload_size(n_sub);
} else {
fprintf(stderr,"Reading MAC PDU: negative payload for last subheader\n");
ERROR("Reading MAC PDU: negative payload for last subheader\n");
}
}
}
@ -129,8 +129,11 @@ uint8_t* sch_pdu::write_packet(srslte::log *log_h)
header_sz += onetwo_padding;
}
if (ce_payload_sz + header_sz >= sdu_offset_start) {
fprintf(stderr, "Writing PDU: header sz + ce_payload_sz >= sdu_offset_start (%d>=%d). pdu_len=%d, total_sdu_len=%d\n",
header_sz + ce_payload_sz, sdu_offset_start, pdu_len, total_sdu_len);
ERROR("Writing PDU: header sz + ce_payload_sz >= sdu_offset_start (%d>=%d). pdu_len=%d, total_sdu_len=%d\n",
header_sz + ce_payload_sz,
sdu_offset_start,
pdu_len,
total_sdu_len);
return NULL;
}
@ -186,29 +189,47 @@ uint8_t* sch_pdu::write_packet(srslte::log *log_h)
}
if (rem_len + header_sz + ce_payload_sz + total_sdu_len != pdu_len) {
printf("\n------------------------------\n");
for (int i=0;i<nof_subheaders;i++) {
printf("SUBH %d is_sdu=%d, payload=%d\n", i, subheaders[i].is_sdu(), subheaders[i].get_payload_size());
}
printf("Wrote PDU: pdu_len=%d, header_and_ce=%d (%d+%d), nof_subh=%d, last_sdu=%d, sdu_len=%d, onepad=%d, multi=%d, init_rem_len=%d\n",
pdu_len, header_sz+ce_payload_sz, header_sz, ce_payload_sz,
nof_subheaders, last_sdu_idx, total_sdu_len, onetwo_padding, rem_len, init_rem_len);
fprintf(stderr, "Expected PDU len %d bytes but wrote %d\n", pdu_len, rem_len + header_sz + ce_payload_sz + total_sdu_len);
printf("------------------------------\n");
if (log_h) {
log_h->error("Wrote PDU: pdu_len=%d, header_and_ce=%d (%d+%d), nof_subh=%d, last_sdu=%d, sdu_len=%d, onepad=%d, multi=%d, init_rem_len=%d\n",
pdu_len, header_sz+ce_payload_sz, header_sz, ce_payload_sz,
nof_subheaders, last_sdu_idx, total_sdu_len, onetwo_padding, rem_len, init_rem_len);
log_h->console("\n------------------------------\n");
for (int i = 0; i < nof_subheaders; i++) {
log_h->console("SUBH %d is_sdu=%d, payload=%d\n", i, subheaders[i].is_sdu(), subheaders[i].get_payload_size());
}
log_h->console("Wrote PDU: pdu_len=%d, header_and_ce=%d (%d+%d), nof_subh=%d, last_sdu=%d, sdu_len=%d, "
"onepad=%d, multi=%d, init_rem_len=%d\n",
pdu_len,
header_sz + ce_payload_sz,
header_sz,
ce_payload_sz,
nof_subheaders,
last_sdu_idx,
total_sdu_len,
onetwo_padding,
rem_len,
init_rem_len);
ERROR("Expected PDU len %d bytes but wrote %d\n", pdu_len, rem_len + header_sz + ce_payload_sz + total_sdu_len);
log_h->console("------------------------------\n");
log_h->error("Wrote PDU: pdu_len=%d, header_and_ce=%d (%d+%d), nof_subh=%d, last_sdu=%d, sdu_len=%d, onepad=%d, "
"multi=%d, init_rem_len=%d\n",
pdu_len,
header_sz + ce_payload_sz,
header_sz,
ce_payload_sz,
nof_subheaders,
last_sdu_idx,
total_sdu_len,
onetwo_padding,
rem_len,
init_rem_len);
}
return NULL;
}
if ((int)(header_sz + ce_payload_sz) != (int) (ptr - pdu_start_ptr)) {
fprintf(stderr, "Expected a header and CE payload of %d bytes but wrote %d\n",
header_sz+ce_payload_sz,(int) (ptr - pdu_start_ptr));
ERROR("Expected a header and CE payload of %d bytes but wrote %d\n",
header_sz + ce_payload_sz,
(int)(ptr - pdu_start_ptr));
return NULL;
}
@ -352,6 +373,8 @@ uint32_t sch_subh::sizeof_ce(uint32_t lcid, bool is_ul)
return 0;
case PADDING:
return 0;
case SCELL_ACTIVATION:
return 1;
}
}
}
@ -458,6 +481,16 @@ uint8_t sch_subh::get_ta_cmd()
}
}
uint8_t sch_subh::get_activation_deactivation_cmd()
{
/* 3GPP 36.321 section 6.1.3.8 Activation/Deactivation MAC Control Element */
if (payload) {
return payload[0];
} else {
return 0;
}
}
uint32_t sch_subh::get_sdu_lcid()
{
return lcid;

@ -45,7 +45,7 @@ void pdu_queue::init(process_callback *callback_, log* log_h_)
uint8_t* pdu_queue::request(uint32_t len)
{
if (len > MAX_PDU_LEN) {
fprintf(stderr, "Error request buffer of invalid size %d. Max bytes %d\n", len, MAX_PDU_LEN);
ERROR("Error request buffer of invalid size %d. Max bytes %d\n", len, MAX_PDU_LEN);
return NULL;
}
pdu_t* pdu = pool.allocate("pdu_queue::request", true);
@ -53,10 +53,10 @@ uint8_t* pdu_queue::request(uint32_t len)
if (log_h) {
log_h->error("Not enough buffers for MAC PDU\n");
}
fprintf(stderr, "Not enough buffers for MAC PDU\n");
ERROR("Not enough buffers for MAC PDU\n");
}
if ((void*) pdu->ptr != (void*) pdu) {
fprintf(stderr, "Fatal error in memory alignment in struct pdu_queue::pdu_t\n");
ERROR("Fatal error in memory alignment in struct pdu_queue::pdu_t\n");
exit(-1);
}
@ -74,12 +74,11 @@ void pdu_queue::deallocate(uint8_t* pdu)
* This function enqueues the packet and returns quicly because ACK
* deadline is important here.
*/
void pdu_queue::push(uint8_t *ptr, uint32_t len, channel_t channel, uint32_t tstamp)
void pdu_queue::push(uint8_t* ptr, uint32_t len, channel_t channel)
{
if (ptr) {
pdu_t *pdu = (pdu_t*) ptr;
pdu->len = len;
pdu->tstamp = tstamp;
pdu->channel = channel;
pdu_q.push(pdu);
} else {
@ -94,7 +93,7 @@ bool pdu_queue::process_pdus()
pdu_t *pdu;
while(pdu_q.try_pop(&pdu)) {
if (callback) {
callback->process_pdu(pdu->ptr, pdu->len, pdu->channel, pdu->tstamp);
callback->process_pdu(pdu->ptr, pdu->len, pdu->channel);
}
cnt++;
have_data = true;

@ -65,7 +65,7 @@ bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void
}
if (pthread_attr_setschedparam(&attr, &param)) {
perror("pthread_attr_setschedparam");
fprintf(stderr, "Error not enough privileges to set Scheduling priority\n");
ERROR("Error not enough privileges to set Scheduling priority\n");
}
attr_enable = true;
} else if (prio_offset == -1) {
@ -79,7 +79,7 @@ bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void
}
if (pthread_attr_setschedparam(&attr, &param)) {
perror("pthread_attr_setschedparam");
fprintf(stderr, "Error not enough privileges to set Scheduling priority\n");
ERROR("Error not enough privileges to set Scheduling priority\n");
}
attr_enable = true;
} else if (prio_offset == -2) {

@ -34,8 +34,8 @@ add_subdirectory(modem)
add_subdirectory(resampling)
add_subdirectory(scrambling)
add_subdirectory(ue)
if(ENABLE_SRSENB)
add_subdirectory(enb)
set(srslte_srcs $<TARGET_OBJECTS:srslte_agc>
$<TARGET_OBJECTS:srslte_ch_estimation>
$<TARGET_OBJECTS:srslte_phy_common>
@ -53,6 +53,26 @@ set(srslte_srcs $<TARGET_OBJECTS:srslte_agc>
$<TARGET_OBJECTS:srslte_ue>
$<TARGET_OBJECTS:srslte_enb>
)
else(ENABLE_SRSENB)
set(srslte_srcs $<TARGET_OBJECTS:srslte_agc>
$<TARGET_OBJECTS:srslte_ch_estimation>
$<TARGET_OBJECTS:srslte_phy_common>
$<TARGET_OBJECTS:srslte_fec>
$<TARGET_OBJECTS:srslte_mimo>
$<TARGET_OBJECTS:srslte_phch>
$<TARGET_OBJECTS:srslte_sync>
$<TARGET_OBJECTS:srslte_utils>
$<TARGET_OBJECTS:srslte_channel>
$<TARGET_OBJECTS:srslte_dft>
$<TARGET_OBJECTS:srslte_io>
$<TARGET_OBJECTS:srslte_modem>
$<TARGET_OBJECTS:srslte_resampling>
$<TARGET_OBJECTS:srslte_scrambling>
$<TARGET_OBJECTS:srslte_ue>
)
endif(ENABLE_SRSENB)
add_library(srslte_phy STATIC ${srslte_srcs})
target_link_libraries(srslte_phy ${FFT_LIBRARIES})

@ -158,7 +158,7 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
y = t[srslte_vec_max_fi(t, 2*len)];// take only positive max to avoid abs() (should be similar)
break;
default:
fprintf(stderr, "Unsupported AGC mode\n");
ERROR("Unsupported AGC mode\n");
return;
}
@ -174,7 +174,7 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
y = q->y_tmp[srslte_vec_max_fi(q->y_tmp, q->nof_frames)];
break;
default:
fprintf(stderr, "Unsupported AGC mode\n");
ERROR("Unsupported AGC mode\n");
return;
}
}

@ -37,7 +37,7 @@
#include "srslte/phy/utils/vector.h"
#include "srslte/phy/utils/convolution.h"
void srslte_chest_set_triangle_filter(float *fil, int filter_len)
uint32_t srslte_chest_set_triangle_filter(float* fil, int filter_len)
{
for (int i=0;i<filter_len/2;i++) {
fil[i] = i+1;
@ -52,6 +52,7 @@ void srslte_chest_set_triangle_filter(float *fil, int filter_len)
for (int i=0;i<filter_len;i++) {
fil[i]/=s;
}
return filter_len;
}
/* Uses the difference between the averaged and non-averaged pilot estimates */
@ -65,11 +66,32 @@ float srslte_chest_estimate_noise_pilots(cf_t *noisy, cf_t *noiseless, cf_t *noi
return power;
}
void srslte_chest_set_smooth_filter3_coeff(float *smooth_filter, float w)
uint32_t srslte_chest_set_smooth_filter3_coeff(float* smooth_filter, float w)
{
smooth_filter[0] = w;
smooth_filter[2] = w;
smooth_filter[1] = 1 - 2 * w;
return 3;
}
uint32_t srslte_chest_set_smooth_filter_gauss(float* filter, uint32_t order, float std_dev)
{
const uint32_t filterlen = order + 1;
const int center = (filterlen - 1) / 2;
float norm_p = 0.0f;
if (filterlen) {
for (int i = 0; i < filterlen; i++) {
filter[i] = expf(-powf(i - center, 2) / (2.0f * powf(std_dev, 2)));
norm_p += powf(filter[i], 2);
}
const float norm = srslte_vec_acc_ff(filter, filterlen);
srslte_vec_sc_prod_fff(filter, 1.0f / norm, filter, filterlen);
}
return filterlen;
}
void srslte_chest_average_pilots(cf_t *input, cf_t *output, float *filter,

@ -24,16 +24,13 @@
*
*/
#include "srslte/srslte.h"
#include <complex.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <complex.h>
#include <math.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/srslte.h>
#include <strings.h>
#include "srslte/config.h"
@ -74,23 +71,22 @@ 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, uint32_t max_prb)
int srslte_chest_dl_init(srslte_chest_dl_t* q, uint32_t max_prb, uint32_t nof_rx_antennas)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL)
{
bzero(q, sizeof(srslte_chest_dl_t));
ret = srslte_refsignal_cs_init(&q->csr_refs, max_prb);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
ERROR("Error initializing CSR signal (%d)\n", ret);
goto clean_exit;
}
q->mbsfn_refs = calloc(SRSLTE_MAX_MBSFN_AREA_IDS, sizeof(srslte_refsignal_t));
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);
ERROR("Calloc error initializing mbsfn_refs (%d)\n", ret);
goto clean_exit;
}
@ -132,33 +128,26 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb)
}
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*max_prb)) {
fprintf(stderr, "Error initializing vector interpolator\n");
ERROR("Error initializing vector interpolator\n");
goto clean_exit;
}
if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*max_prb, SRSLTE_NRE/2)) {
fprintf(stderr, "Error initializing interpolator\n");
ERROR("Error initializing interpolator\n");
goto clean_exit;
}
if (srslte_interp_linear_init(&q->srslte_interp_lin_3, 4*max_prb, SRSLTE_NRE/4)) {
fprintf(stderr, "Error initializing interpolator\n");
ERROR("Error initializing interpolator\n");
goto clean_exit;
}
if (srslte_interp_linear_init(&q->srslte_interp_lin_mbsfn, 6*max_prb, SRSLTE_NRE/6)) {
fprintf(stderr, "Error initializing interpolator\n");
ERROR("Error initializing interpolator\n");
goto clean_exit;
}
q->noise_alg = SRSLTE_NOISE_ALG_REFS;
q->rsrp_neighbour = false;
q->average_subframe = false;
q->smooth_filter_auto = false;
q->smooth_filter_len = 3;
srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1);
q->nof_rx_antennas = nof_rx_antennas;
}
ret = SRSLTE_SUCCESS;
@ -207,8 +196,58 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q)
bzero(q, sizeof(srslte_chest_dl_t));
}
int srslte_chest_dl_res_init(srslte_chest_dl_res_t* q, uint32_t max_prb)
{
bzero(q, sizeof(srslte_chest_dl_res_t));
q->nof_re = SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM);
for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (uint32_t j = 0; j < SRSLTE_MAX_PORTS; j++) {
q->ce[i][j] = srslte_vec_malloc(q->nof_re * sizeof(cf_t));
if (!q->ce[i][j]) {
perror("malloc");
return -1;
}
bzero(q->ce[i][j], SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
}
}
return 0;
}
void srslte_chest_dl_res_set_identity(srslte_chest_dl_res_t* q)
{
for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (uint32_t j = 0; j < SRSLTE_MAX_PORTS; j++) {
for (uint32_t k = 0; k < q->nof_re; k++) {
q->ce[i][j][k] = (i == j) ? 1.0f : 0.0f;
}
}
}
}
void srslte_chest_dl_res_set_ones(srslte_chest_dl_res_t* q)
{
for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (uint32_t j = 0; j < SRSLTE_MAX_PORTS; j++) {
for (uint32_t k = 0; k < q->nof_re; k++) {
q->ce[i][j][k] = 1.0f;
}
}
}
}
void srslte_chest_dl_res_free(srslte_chest_dl_res_t* q)
{
for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (uint32_t j = 0; j < SRSLTE_MAX_PORTS; j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
}
}
int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t *q, uint16_t mbsfn_area_id){
int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t* q, uint16_t mbsfn_area_id)
{
if (mbsfn_area_id < SRSLTE_MAX_MBSFN_AREA_IDS) {
if (!q->mbsfn_refs[mbsfn_area_id]) {
q->mbsfn_refs[mbsfn_area_id] = calloc(1, sizeof(srslte_refsignal_t));
@ -233,28 +272,28 @@ int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell)
srslte_cell_isvalid(&cell))
{
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
q->cell = cell;
ret = srslte_refsignal_cs_set_cell(&q->csr_refs, cell);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
ERROR("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");
ERROR("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");
ERROR("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");
ERROR("Error initializing interpolator\n");
return SRSLTE_ERROR;
}
if (srslte_interp_linear_resize(&q->srslte_interp_lin_3, 4 * q->cell.nof_prb, SRSLTE_NRE / 4)) {
fprintf(stderr, "Error initializing interpolator\n");
ERROR("Error initializing interpolator\n");
return SRSLTE_ERROR;
}
if (srslte_interp_linear_resize(&q->srslte_interp_lin_mbsfn, 6 * q->cell.nof_prb, SRSLTE_NRE / 6)) {
@ -269,19 +308,33 @@ int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell)
}
/* 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, srslte_sf_t ch_mode)
static float estimate_noise_pilots(srslte_chest_dl_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id)
{
srslte_sf_t ch_mode = sf->sf_type;
const float weight = 1.0f;
float sum_power = 0.0f;
uint32_t count = 0;
uint32_t npilots = (ch_mode == SRSLTE_SF_MBSFN)?SRSLTE_REFSIGNAL_NUM_SF_MBSFN(q->cell.nof_prb, port_id):SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN) ? srslte_refsignal_mbsfn_nof_symbols() : srslte_refsignal_cs_nof_symbols(port_id);
uint32_t npilots = (ch_mode == SRSLTE_SF_MBSFN) ? SRSLTE_REFSIGNAL_NUM_SF_MBSFN(q->cell.nof_prb, port_id)
: srslte_refsignal_cs_nof_re(&q->csr_refs, sf, port_id);
uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN) ? srslte_refsignal_mbsfn_nof_symbols()
: srslte_refsignal_cs_nof_symbols(&q->csr_refs, sf, port_id);
uint32_t nref = npilots / nsymbols;
uint32_t fidx = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_fidx(1):srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0);
cf_t *input2d[nsymbols + 2];
cf_t *tmp_noise = q->tmp_noise;
// Special case for 1 symbol
if (nsymbols == 1) {
srslte_vec_sc_prod_cfc(q->pilot_estimates + 1, weight, tmp_noise, nref - 2);
srslte_vec_sum_ccc(q->pilot_estimates + 0, tmp_noise, tmp_noise, nref - 2);
srslte_vec_sum_ccc(q->pilot_estimates + 2, tmp_noise, tmp_noise, nref - 2);
srslte_vec_sc_prod_cfc(tmp_noise, 1.0f / (weight + 2.0f), tmp_noise, nref - 2);
srslte_vec_sub_ccc(q->pilot_estimates + 1, tmp_noise, tmp_noise, nref - 2);
sum_power = srslte_vec_avg_power_cf(tmp_noise, nref - 2);
return sum_power;
}
for (int i = 0; i < nsymbols; i++) {
input2d[i + 1] = &q->pilot_estimates[i * nref];
}
@ -366,21 +419,28 @@ 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, srslte_sf_t ch_mode)
static void interpolate_pilots(srslte_chest_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_cfg_t* cfg,
cf_t* pilot_estimates,
cf_t* ce,
uint32_t port_id)
{
/* interpolate the symbols with references in the freq domain */
uint32_t l;
uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN ) ? srslte_refsignal_mbsfn_nof_symbols() + 1 : srslte_refsignal_cs_nof_symbols(port_id);
uint32_t nsymbols = (sf->sf_type == SRSLTE_SF_MBSFN) ? srslte_refsignal_mbsfn_nof_symbols() + 1
: srslte_refsignal_cs_nof_symbols(&q->csr_refs, sf, port_id);
uint32_t fidx_offset = 0;
/* Interpolate in the frequency domain */
if (q->average_subframe) {
nsymbols = 1;
uint32_t freq_nsymbols = nsymbols;
if (!cfg->interpolate_subframe) {
freq_nsymbols = 1;
}
// 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) {
for (uint32_t l = 0; l < freq_nsymbols; l++) {
if (sf->sf_type == 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],
@ -394,7 +454,7 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
}
} else {
if (q->average_subframe) {
if (!cfg->interpolate_subframe && nsymbols > 1) {
fidx_offset = q->cell.id % 3;
srslte_interp_linear_offset(&q->srslte_interp_lin_3,
pilot_estimates,
@ -411,31 +471,38 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
}
/* Now interpolate in the time domain between symbols */
if (q->average_subframe) {
if (sf->sf_type == SRSLTE_SF_NORM && (!cfg->interpolate_subframe || nsymbols < 3)) {
// If we average per subframe, just copy the estimates in the time domain
for (l=1;l<2*SRSLTE_CP_NSYMB(q->cell.cp);l++) {
for (uint32_t l = 1; l < 2 * SRSLTE_CP_NSYMB(q->cell.cp); l++) {
memcpy(&ce[l*SRSLTE_NRE*q->cell.nof_prb], ce, sizeof(cf_t)*SRSLTE_NRE*q->cell.nof_prb);
}
} else {
if (ch_mode == SRSLTE_SF_MBSFN) {
if (sf->sf_type == 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) {
if (port_id <= 2) {
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);
if (nsymbols == 4) {
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);
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(4), &cesymb(7), &cesymb(7), &cesymb(8), 3, 6);
}
} 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) {
if (port_id <= 2) {
// TODO: TDD and extended cyclic prefix
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);
@ -450,95 +517,22 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
}
}
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) {
memcpy(q->smooth_filter, filter, filter_len*sizeof(float));
q->smooth_filter_len = filter_len;
} else {
q->smooth_filter_len = 0;
}
} else {
fprintf(stderr, "Error setting smoothing filter: filter len exceeds maximum (%d>%d)\n",
filter_len, SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN);
}
}
void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q, srslte_chest_dl_noise_alg_t noise_estimation_alg) {
q->noise_alg = noise_estimation_alg;
}
void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w)
{
q->smooth_filter_len = 3;
q->smooth_filter[0] = w;
q->smooth_filter[2] = w;
q->smooth_filter[1] = 1-2*w;
}
void srslte_chest_dl_set_smooth_filter_gauss(srslte_chest_dl_t* q, uint32_t order, float std_dev)
static void average_pilots(srslte_chest_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_cfg_t* cfg,
cf_t* input,
cf_t* output,
uint32_t port_id,
float* filter,
uint32_t filter_len)
{
const uint32_t filterlen = order + 1;
const int center = (filterlen - 1) / 2;
float *filter = q->smooth_filter;
float norm_p = 0.0f;
if (filterlen) {
for (int i = 0; i < filterlen; i++) {
filter[i] = expf(-powf(i - center, 2) / (2.0f * powf(std_dev, 2)));
norm_p += powf(filter[i], 2);
}
const float norm = srslte_vec_acc_ff(filter, filterlen);
srslte_vec_sc_prod_fff(filter, 1.0f / norm, filter, filterlen);
q->smooth_filter_len = filterlen;
}
}
void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t *q, bool enable) {
q->smooth_filter_auto = enable;
}
uint32_t srslte_chest_dl_interleave_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *tmp, 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;
uint32_t fidx = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_fidx(1):srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0);
if (fidx < 3) {
srslte_vec_interleave(input, &input[nref], tmp, nref);
for (int l = 2; l < nsymbols - 1; l += 2) {
srslte_vec_interleave_add(&input[l * nref], &input[(l + 1) * nref], tmp, nref);
}
} else {
srslte_vec_interleave(&input[nref], input, tmp, nref);
for (int l = 2; l < nsymbols - 1; l += 2) {
srslte_vec_interleave_add(&input[(l + 1) * nref], &input[l * nref], tmp, nref);
}
}
nref *= 2;
srslte_vec_sc_prod_cfc(tmp, 2.0f / nsymbols, output, nref);
return nref;
}
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;
uint32_t nsymbols = (sf->sf_type == SRSLTE_SF_MBSFN) ? srslte_refsignal_mbsfn_nof_symbols(port_id)
: srslte_refsignal_cs_nof_symbols(&q->csr_refs, sf, port_id);
uint32_t nref = (sf->sf_type == SRSLTE_SF_MBSFN) ? 6 * q->cell.nof_prb : 2 * q->cell.nof_prb;
// Average in the time domain if enabled
if (q->average_subframe) {
if (ch_mode == SRSLTE_SF_MBSFN) {
for (int l = 1; l < nsymbols; l++) {
srslte_vec_sum_ccc(&input[l * nref], input, input, nref);
}
srslte_vec_sc_prod_cfc(input, 1.0f / ((float) nsymbols), input, nref);
nsymbols = 1;
} else {
cf_t *temp = output; // Use ouput as temporal buffer
if (!cfg->interpolate_subframe && nsymbols > 1) {
cf_t* temp = output; // Use output as temporal buffer
if (srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0) < 3) {
srslte_vec_interleave(input, &input[nref], temp, nref);
@ -556,26 +550,24 @@ static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint
nsymbols = 1;
}
}
uint32_t skip = (ch_mode == SRSLTE_SF_MBSFN)?2*q->cell.nof_prb:0;
if(ch_mode == SRSLTE_SF_MBSFN){
uint32_t skip = (sf->sf_type == SRSLTE_SF_MBSFN) ? 2 * q->cell.nof_prb : 0;
if (sf->sf_type == SRSLTE_SF_MBSFN) {
memcpy(&output[0],&input[0],skip*sizeof(cf_t));
}
// Average in the frequency domain
for (int l=0;l<nsymbols;l++) {
srslte_conv_same_cf(&input[l*nref + skip], q->smooth_filter, &output[l*nref + skip], nref, q->smooth_filter_len);
srslte_conv_same_cf(&input[l * nref + skip], filter, &output[l * nref + skip], nref, filter_len);
}
}
float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id) {
static float chest_dl_rssi(srslte_chest_dl_t* q, srslte_dl_sf_cfg_t* sf, cf_t* input, uint32_t port_id)
{
uint32_t l;
float rssi = 0;
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id);
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(&q->csr_refs, sf, port_id);
for (l=0;l<nsymbols;l++) {
cf_t *tmp = &input[srslte_refsignal_cs_nsymbol(l, q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE];
rssi += srslte_vec_dot_prod_conj_ccc(tmp, tmp, q->cell.nof_prb * SRSLTE_NRE);
@ -585,13 +577,16 @@ float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id)
// CFO estimation algorithm taken from "Carrier Frequency Synchronization in the
// Downlink of 3GPP LTE", Qi Wang, C. Mehlfuhrer, M. Rupp
float chest_estimate_cfo(srslte_chest_dl_t *q)
static float chest_estimate_cfo(srslte_chest_dl_t* q)
{
float n = (float)srslte_symbol_sz(q->cell.nof_prb);
float ns = (float)SRSLTE_CP_NSYMB(q->cell.cp);
float ng = (float)SRSLTE_CP_LEN_NORM(1, n);
uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 0);
srslte_dl_sf_cfg_t sf_cfg;
ZERO_OBJECT(sf_cfg);
uint32_t npilots = srslte_refsignal_cs_nof_re(&q->csr_refs, &sf_cfg, 0);
// Compute angles between slots
for (int i=0;i<2;i++) {
@ -607,202 +602,186 @@ float chest_estimate_cfo(srslte_chest_dl_t *q)
return -cargf(sum) * n / (ns * (n + ng)) / 2 / M_PI;
}
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 (q->cfo_estimate_enable && ((1<<sf_idx) & q->cfo_estimate_sf_mask) && ch_mode != SRSLTE_SF_MBSFN ) {
static void chest_interpolate_noise_est(srslte_chest_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_cfg_t* cfg,
cf_t* input,
cf_t* ce,
uint32_t port_id,
uint32_t rxant_id)
{
float filter[SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN];
uint32_t filter_len = 0;
uint32_t sf_idx = sf->tti % 10;
srslte_sf_t ch_mode = sf->sf_type;
if (cfg->cfo_estimate_enable && ((1 << sf_idx) & cfg->cfo_estimate_sf_mask) && ch_mode != SRSLTE_SF_MBSFN) {
q->cfo = chest_estimate_cfo(q);
}
/* Estimate noise */
if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && ch_mode != SRSLTE_SF_MBSFN ) {
q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode);
if (cfg->noise_alg == SRSLTE_NOISE_ALG_REFS) {
if (ch_mode == SRSLTE_SF_MBSFN) {
ERROR("Warning: REFS noise estimation algorithm not supported in MBSFN subframes\n");
}
q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, sf, port_id);
}
if (ce != NULL) {
if (q->smooth_filter_auto) {
srslte_chest_dl_set_smooth_filter_gauss(q, 4, q->noise_estimate[rxant_id][port_id] * 200.0f);
switch (cfg->filter_type) {
case SRSLTE_CHEST_FILTER_GAUSS:
if (ch_mode == SRSLTE_SF_MBSFN) {
ERROR("Warning: Gauss filter not supported in MBSFN subframes\n");
}
if (cfg->filter_coef[0] <= 0) {
filter_len = srslte_chest_set_smooth_filter_gauss(filter, 4, q->noise_estimate[rxant_id][port_id] * 200.0f);
} else {
filter_len = srslte_chest_set_smooth_filter_gauss(filter, (uint32_t)cfg->filter_coef[0], cfg->filter_coef[1]);
}
break;
case SRSLTE_CHEST_FILTER_TRIANGLE:
filter_len = srslte_chest_set_smooth_filter3_coeff(filter, cfg->filter_coef[0]);
break;
default:
break;
}
if (!cfg->interpolate_subframe && ch_mode == SRSLTE_SF_MBSFN) {
ERROR("Warning: Subframe interpolation must be enabled in MBSFN subframes\n");
}
/* 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, ch_mode);
if (cfg->filter_type == SRSLTE_CHEST_FILTER_NONE) {
interpolate_pilots(q, sf, cfg, q->pilot_estimates, ce, port_id);
} else {
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);
average_pilots(q, sf, cfg, q->pilot_estimates, q->pilot_estimates_average, port_id, filter, filter_len);
interpolate_pilots(q, sf, cfg, q->pilot_estimates_average, ce, port_id);
}
/* Estimate noise power */
if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) {
/* Estimate noise for PSS and EMPTY algorithms */
switch (cfg->noise_alg) {
case SRSLTE_NOISE_ALG_PSS:
if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[rxant_id][port_id] = estimate_noise_pss(q, input, ce);
}
} else if (q->noise_alg != SRSLTE_NOISE_ALG_REFS) {
break;
case SRSLTE_NOISE_ALG_EMPTY:
if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input);
}
break;
default:
break;
}
}
}
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)
static int estimate_port(srslte_chest_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_cfg_t* cfg,
cf_t* input,
cf_t* ce,
uint32_t port_id,
uint32_t rxant_id)
{
uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
uint32_t npilots = srslte_refsignal_cs_nof_re(&q->csr_refs, sf, port_id);
/* Get references from the input signal */
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
srslte_refsignal_cs_get_sf(&q->csr_refs, sf, 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, npilots);
srslte_vec_prod_conj_ccc(
q->pilot_recv_signal, q->csr_refs.pilots[port_id / 2][sf->tti % 10], q->pilot_estimates, npilots);
/* Compute RSRP for the channel estimates in this port */
if (q->rsrp_neighbour) {
if (cfg->rsrp_neighbour) {
double energy = cabs(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots);
q->rsrp_corr[rxant_id][port_id] = energy * energy;
}
q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_recv_signal, npilots);
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
q->rssi[rxant_id][port_id] = chest_dl_rssi(q, sf, input, port_id);
chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_NORM);
chest_interpolate_noise_est(q, sf, cfg, input, ce, port_id, rxant_id);
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)
static int estimate_port_mbsfn(srslte_chest_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_cfg_t* cfg,
cf_t* input,
cf_t* ce,
uint32_t port_id,
uint32_t rxant_id)
{
uint32_t sf_idx = sf->tti % 10;
uint16_t mbsfn_area_id = cfg->mbsfn_area_id;
if (!q->mbsfn_refs[mbsfn_area_id]) {
ERROR("Error in chest_dl: MBSFN area id=%d not initialized\n", cfg->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, 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);
chest_interpolate_noise_est(q, sf, cfg, input, ce, port_id, rxant_id);
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++) {
for (uint32_t port_id=0;port_id<q->cell.nof_ports;port_id++) {
if (srslte_chest_dl_estimate_port(q, input[rxant_id], ce[port_id][rxant_id], sf_idx, port_id, rxant_id)) {
return SRSLTE_ERROR;
}
}
}
q->last_nof_antennas = nof_rx_antennas;
return SRSLTE_SUCCESS;
}
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;
}
}
q->last_nof_antennas = 1;
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;
}
void srslte_chest_dl_set_rsrp_neighbour(srslte_chest_dl_t *q, bool rsrp_for_neighbour) {
q->rsrp_neighbour = rsrp_for_neighbour;
}
void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, bool enable)
static float get_noise(srslte_chest_dl_t* q)
{
q->average_subframe = enable;
}
void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, bool enable, uint32_t mask)
{
q->cfo_estimate_enable = enable;
q->cfo_estimate_sf_mask = mask;
}
float srslte_chest_dl_get_cfo(srslte_chest_dl_t *q) {
return q->cfo;
}
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++) {
for (int i = 0; i < q->nof_rx_antennas; i++) {
n += srslte_vec_acc_ff(q->noise_estimate[i], q->cell.nof_ports)/q->cell.nof_ports;
}
if (q->last_nof_antennas) {
n /= q->last_nof_antennas;
if (q->nof_rx_antennas) {
n /= q->nof_rx_antennas;
}
return n;
}
float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) {
#ifdef FREQ_SEL_SNR
int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 0);
return srslte_vec_acc_ff(q->snr_vector, nref)/nref;
#else
float rsrp = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
for (int j=0;j<q->cell.nof_ports;j++) {
rsrp += q->rsrp[i][j]/q->cell.nof_ports;
}
}
return rsrp/srslte_chest_dl_get_noise_estimate(q);
#endif
}
float srslte_chest_dl_get_snr_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port_idx) {
return srslte_chest_dl_get_rsrp_ant_port(q, ant_idx, port_idx)/srslte_chest_dl_get_noise_estimate(q);
}
float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) {
static float get_rssi(srslte_chest_dl_t* q)
{
float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
for (int i = 0; i < q->nof_rx_antennas; i++) {
n += 4 * q->rssi[i][0] / q->cell.nof_prb / SRSLTE_NRE;
}
return n/q->last_nof_antennas;
return n / q->nof_rx_antennas;
}
/* q->rssi[0] is the average power in all RE in all symbol containing references for port 0 . q->rssi[0]/q->cell.nof_prb is the average power per PRB
* q->rsrp[0] is the average power of RE containing references only (for port 0).
/* q->rssi[0] is the average power in all RE in all symbol containing references for port 0 . q->rssi[0]/q->cell.nof_prb
* is the average power per PRB q->rsrp[0] is the average power of RE containing references only (for port 0).
*/
float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q) {
static float get_rsrq(srslte_chest_dl_t* q)
{
float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
for (int i = 0; i < q->nof_rx_antennas; i++) {
n += q->cell.nof_prb*q->rsrp[i][0] / q->rssi[i][0];
}
return n/q->last_nof_antennas;
return n / q->nof_rx_antennas;
}
float srslte_chest_dl_get_rsrq_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port_idx) {
return q->cell.nof_prb*q->rsrp[ant_idx][port_idx] / q->rssi[ant_idx][port_idx];
}
float srslte_chest_dl_get_rsrp_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port) {
float srslte_chest_dl_get_rsrp_ant_port(srslte_chest_dl_t* q, uint32_t ant_idx, uint32_t port)
{
return q->rsrp[ant_idx][port];
}
float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) {
static float get_rsrp_port(srslte_chest_dl_t* q, uint32_t port)
{
float sum = 0.0f;
for (int j = 0; j < q->cell.nof_ports; ++j) {
sum +=q->rsrp[port][j];
@ -815,7 +794,8 @@ float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) {
return sum;
}
float srslte_chest_dl_get_rsrp_neighbour_port(srslte_chest_dl_t *q, uint32_t port) {
static float get_rsrp_neigbhour_port(srslte_chest_dl_t* q, uint32_t port)
{
float sum = 0.0f;
for (int j = 0; j < q->cell.nof_ports; ++j) {
sum +=q->rsrp_corr[port][j];
@ -828,10 +808,11 @@ float srslte_chest_dl_get_rsrp_neighbour_port(srslte_chest_dl_t *q, uint32_t por
return sum;
}
float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) {
static float get_rsrp(srslte_chest_dl_t* q)
{
float max = -1e9;
for (int i = 0; i < q->last_nof_antennas; ++i) {
float v = srslte_chest_dl_get_rsrp_port(q, i);
for (int i = 0; i < q->nof_rx_antennas; ++i) {
float v = get_rsrp_port(q, i);
if (v > max) {
max = v;
}
@ -839,13 +820,82 @@ float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) {
return max;
}
float srslte_chest_dl_get_rsrp_neighbour(srslte_chest_dl_t *q) {
static float get_snr(srslte_chest_dl_t* q)
{
#ifdef FREQ_SEL_SNR
int nref = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 0);
return srslte_vec_acc_ff(q->snr_vector, nref) / nref;
#else
return get_rsrp(q) / get_noise(q);
#endif
}
static float get_rsrp_neighbour(srslte_chest_dl_t* q)
{
float max = -1e9;
for (int i = 0; i < q->last_nof_antennas; ++i) {
float v = srslte_chest_dl_get_rsrp_neighbour_port(q, i);
for (int i = 0; i < q->nof_rx_antennas; ++i) {
float v = get_rsrp_neigbhour_port(q, i);
if (v > max) {
max = v;
}
}
return max;
}
#define dbm(a) (10 * log10(a) + 30)
#define db(a) (10 * log10(a))
static void fill_res(srslte_chest_dl_t* q, srslte_chest_dl_res_t* res)
{
res->noise_estimate = get_noise(q);
res->noise_estimate_dbm = dbm(res->noise_estimate);
res->cfo = q->cfo;
res->rsrp = get_rsrp(q);
res->rsrp_dbm = dbm(res->rsrp);
res->rsrp_neigh_dbm = dbm(get_rsrp_neighbour(q));
res->rsrq = get_rsrq(q);
res->rsrq_db = db(res->rsrq);
res->snr_db = db(get_snr(q));
res->rssi_dbm = dbm(get_rssi(q));
for (uint32_t port_id = 0; port_id < q->cell.nof_ports; port_id++) {
res->rsrp_port_dbm[port_id] = dbm(get_rsrp_port(q, port_id));
}
}
int srslte_chest_dl_estimate(srslte_chest_dl_t* q,
srslte_dl_sf_cfg_t* sf,
cf_t* input[SRSLTE_MAX_PORTS],
srslte_chest_dl_res_t* res)
{
srslte_chest_dl_cfg_t cfg;
ZERO_OBJECT(cfg);
return srslte_chest_dl_estimate_cfg(q, sf, &cfg, input, res);
}
int srslte_chest_dl_estimate_cfg(srslte_chest_dl_t* q,
srslte_dl_sf_cfg_t* sf,
srslte_chest_dl_cfg_t* cfg,
cf_t* input[SRSLTE_MAX_PORTS],
srslte_chest_dl_res_t* res)
{
for (uint32_t rxant_id = 0; rxant_id < q->nof_rx_antennas; rxant_id++) {
for (uint32_t port_id = 0; port_id < q->cell.nof_ports; port_id++) {
if (sf->sf_type == SRSLTE_SF_MBSFN) {
if (estimate_port_mbsfn(q, sf, cfg, input[rxant_id], res->ce[port_id][rxant_id], port_id, rxant_id)) {
return SRSLTE_ERROR;
}
} else {
if (estimate_port(q, sf, cfg, input[rxant_id], res->ce[port_id][rxant_id], port_id, rxant_id)) {
return SRSLTE_ERROR;
}
}
}
}
fill_res(q, res);
return SRSLTE_SUCCESS;
}

@ -32,15 +32,13 @@
#include <string.h>
#include <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/config.h"
#include "srslte/phy/dft/dft_precoding.h"
#include "srslte/phy/ch_estimation/chest_ul.h"
#include "srslte/phy/utils/vector.h"
#include "srslte/phy/dft/dft_precoding.h"
#include "srslte/phy/utils/convolution.h"
#include "srslte/phy/utils/vector.h"
#include "srslte/srslte.h"
#define NOF_REFS_SYM (q->cell.nof_prb*SRSLTE_NRE)
#define NOF_REFS_SF (NOF_REFS_SYM*2) // 2 reference symbols per subframe
@ -66,7 +64,7 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, uint32_t max_prb)
ret = srslte_refsignal_ul_init(&q->dmrs_signal, max_prb);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
ERROR("Error initializing CSR signal (%d)\n", ret);
goto clean_exit;
}
@ -100,17 +98,17 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, uint32_t max_prb)
}
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, MAX_REFS_SYM)) {
fprintf(stderr, "Error initializing vector interpolator\n");
ERROR("Error initializing vector interpolator\n");
goto clean_exit;
}
q->smooth_filter_len = 3;
srslte_chest_ul_set_smooth_filter3_coeff(q, 0.3333);
srslte_chest_set_smooth_filter3_coeff(q->smooth_filter, 0.3333);
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");
if (srslte_refsignal_dmrs_pusch_pregen_init(&q->dmrs_pregen, max_prb)) {
ERROR("Error allocating memory for pregenerated signals\n");
goto clean_exit;
}
@ -152,6 +150,32 @@ void srslte_chest_ul_free(srslte_chest_ul_t *q)
bzero(q, sizeof(srslte_chest_ul_t));
}
int srslte_chest_ul_res_init(srslte_chest_ul_res_t* q, uint32_t max_prb)
{
bzero(q, sizeof(srslte_chest_ul_res_t));
q->nof_re = SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM);
q->ce = srslte_vec_malloc(q->nof_re * sizeof(cf_t));
if (!q->ce) {
perror("malloc");
return -1;
}
return 0;
}
void srslte_chest_ul_res_set_identity(srslte_chest_ul_res_t* q)
{
for (uint32_t i = 0; i < q->nof_re; i++) {
q->ce[i] = 1.0;
}
}
void srslte_chest_ul_res_free(srslte_chest_ul_res_t* q)
{
if (q->ce) {
free(q->ce);
}
}
int srslte_chest_ul_set_cell(srslte_chest_ul_t* q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -159,15 +183,15 @@ int srslte_chest_ul_set_cell(srslte_chest_ul_t *q, srslte_cell_t cell)
srslte_cell_isvalid(&cell))
{
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
q->cell = cell;
ret = srslte_refsignal_ul_set_cell(&q->dmrs_signal, cell);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
ERROR("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");
ERROR("Error initializing vector interpolator\n");
return SRSLTE_ERROR;
}
}
@ -176,13 +200,9 @@ int srslte_chest_ul_set_cell(srslte_chest_ul_t *q, srslte_cell_t cell)
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,
srslte_refsignal_srs_cfg_t *srs_cfg)
void srslte_chest_ul_pregen(srslte_chest_ul_t* q, srslte_refsignal_dmrs_pusch_cfg_t* cfg)
{
srslte_refsignal_ul_set_cfg(&q->dmrs_signal, pusch_cfg, pucch_cfg, srs_cfg);
srslte_refsignal_dmrs_pusch_pregen(&q->dmrs_signal, &q->dmrs_pregen);
srslte_refsignal_dmrs_pusch_pregen(&q->dmrs_signal, &q->dmrs_pregen, cfg);
q->dmrs_signal_configured = true;
}
@ -214,6 +234,7 @@ static float estimate_noise_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nref
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,n_prb[0]*SRSLTE_NRE)]
static void interpolate_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nrefs, uint32_t n_prb[2])
{
#ifdef DO_LINEAR_INTERPOLATION
uint32_t L1 = SRSLTE_REFSIGNAL_UL_L(0, q->cell.cp);
uint32_t L2 = SRSLTE_REFSIGNAL_UL_L(1, q->cell.cp);
uint32_t NL = 2*SRSLTE_CP_NSYMB(q->cell.cp);
@ -225,27 +246,16 @@ static void interpolate_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nrefs, u
&cesymb(L1), &cesymb(L2), NULL, &cesymb(L1+1), (L2-L1), (L2-L1)-1, true, nrefs);
srslte_interp_linear_vector3(&q->srslte_interp_linvec,
&cesymb(L1), &cesymb(L2), &cesymb(L2), &cesymb(L2+1), (L2-L1), (NL-L2)-1, true, nrefs);
}
void srslte_chest_ul_set_smooth_filter(srslte_chest_ul_t *q, float *filter, uint32_t filter_len) {
if (filter_len < SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN) {
if (filter) {
memcpy(q->smooth_filter, filter, filter_len*sizeof(float));
q->smooth_filter_len = filter_len;
} else {
q->smooth_filter_len = 0;
}
} else {
fprintf(stderr, "Error setting smoothing filter: filter len exceeds maximum (%d>%d)\n",
filter_len, SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN);
#else
// Instead of a linear interpolation, we just copy the estimates to all symbols in that subframe
for (int s = 0; s < 2; s++) {
for (int i = 0; i < SRSLTE_CP_NSYMB(q->cell.cp); i++) {
memcpy(&ce[((i + s * SRSLTE_CP_NSYMB(q->cell.cp)) * q->cell.nof_prb + n_prb[s]) * SRSLTE_NRE],
&ce[(SRSLTE_REFSIGNAL_UL_L(s, q->cell.cp) * q->cell.nof_prb + n_prb[s]) * SRSLTE_NRE],
nrefs * sizeof(cf_t));
}
}
void srslte_chest_ul_set_smooth_filter3_coeff(srslte_chest_ul_t* q, float w)
{
srslte_chest_set_smooth_filter3_coeff(q->smooth_filter, w);
q->smooth_filter_len = 3;
#endif
}
static void average_pilots(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, uint32_t nrefs, uint32_t n_prb[2]) {
@ -256,16 +266,18 @@ static void average_pilots(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, uint32_t
}
}
int srslte_chest_ul_estimate(srslte_chest_ul_t *q, cf_t *input, cf_t *ce,
uint32_t nof_prb, uint32_t sf_idx, uint32_t cyclic_shift_for_dmrs, uint32_t n_prb[2])
int srslte_chest_ul_estimate_pusch(
srslte_chest_ul_t* q, srslte_ul_sf_cfg_t* sf, srslte_pusch_cfg_t* cfg, cf_t* input, srslte_chest_ul_res_t* res)
{
if (!q->dmrs_signal_configured) {
fprintf(stderr, "Error must call srslte_chest_ul_set_cfg() before using the UL estimator\n");
ERROR("Error must call srslte_chest_ul_set_cfg() before using the UL estimator\n");
return SRSLTE_ERROR;
}
uint32_t nof_prb = cfg->grant.L_prb;
if (!srslte_dft_precoding_valid_prb(nof_prb)) {
fprintf(stderr, "Error invalid nof_prb=%d\n", nof_prb);
ERROR("Error invalid nof_prb=%d\n", nof_prb);
return SRSLTE_ERROR_INVALID_INPUTS;
}
@ -273,75 +285,82 @@ int srslte_chest_ul_estimate(srslte_chest_ul_t *q, cf_t *input, cf_t *ce,
int nrefs_sf = nrefs_sym * 2;
/* Get references from the input signal */
srslte_refsignal_dmrs_pusch_get(&q->dmrs_signal, input, nof_prb, n_prb, q->pilot_recv_signal);
srslte_refsignal_dmrs_pusch_get(&q->dmrs_signal, cfg, input, q->pilot_recv_signal);
/* Use the known DMRS signal to compute Least-squares estimates */
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->dmrs_pregen.r[cyclic_shift_for_dmrs][sf_idx][nof_prb],
q->pilot_estimates, nrefs_sf);
srslte_vec_prod_conj_ccc(
q->pilot_recv_signal, q->dmrs_pregen.r[cfg->grant.n_dmrs][sf->tti % 10][nof_prb], q->pilot_estimates, nrefs_sf);
if (n_prb[0] != n_prb[1]) {
if (cfg->grant.n_prb[0] != cfg->grant.n_prb[1]) {
printf("ERROR: intra-subframe frequency hopping not supported in the estimator!!\n");
}
if (ce != NULL) {
if (res->ce != NULL) {
if (q->smooth_filter_len > 0) {
average_pilots(q, q->pilot_estimates, ce, nrefs_sym, n_prb);
interpolate_pilots(q, ce, nrefs_sym, n_prb);
average_pilots(q, q->pilot_estimates, res->ce, nrefs_sym, cfg->grant.n_prb);
interpolate_pilots(q, res->ce, nrefs_sym, cfg->grant.n_prb);
/* If averaging, compute noise from difference between received and averaged estimates */
q->noise_estimate = estimate_noise_pilots(q, ce, nrefs_sym, n_prb);
res->noise_estimate = estimate_noise_pilots(q, res->ce, nrefs_sym, cfg->grant.n_prb);
} else {
// Copy estimates to CE vector without averaging
for (int i=0;i<2;i++) {
memcpy(&ce[SRSLTE_REFSIGNAL_UL_L(i, q->cell.cp)*q->cell.nof_prb*SRSLTE_NRE+n_prb[i]*SRSLTE_NRE],
memcpy(&res->ce[SRSLTE_REFSIGNAL_UL_L(i, q->cell.cp) * q->cell.nof_prb * SRSLTE_NRE +
cfg->grant.n_prb[i] * SRSLTE_NRE],
&q->pilot_estimates[i * nrefs_sym],
nrefs_sym * sizeof(cf_t));
}
interpolate_pilots(q, ce, nrefs_sym, n_prb);
q->noise_estimate = 0;
interpolate_pilots(q, res->ce, nrefs_sym, cfg->grant.n_prb);
res->noise_estimate = 0;
}
}
// Estimate received pilot power
q->pilot_power = srslte_vec_avg_power_cf(q->pilot_recv_signal, nrefs_sf);
if (res->noise_estimate) {
res->snr = srslte_vec_avg_power_cf(q->pilot_recv_signal, nrefs_sf) / res->noise_estimate;
} else {
res->snr = NAN;
}
res->snr_db = 10 * log10(res->snr);
res->noise_estimate_dbm = 10 * log10(res->noise_estimate) + 30;
return 0;
}
int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, cf_t *input, cf_t *ce,
srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx,
uint8_t *pucch2_ack_bits)
int srslte_chest_ul_estimate_pucch(
srslte_chest_ul_t* q, srslte_ul_sf_cfg_t* sf, srslte_pucch_cfg_t* cfg, cf_t* input, srslte_chest_ul_res_t* res)
{
if (!q->dmrs_signal_configured) {
fprintf(stderr, "Error must call srslte_chest_ul_set_cfg() before using the UL estimator\n");
ERROR("Error must call srslte_chest_ul_set_cfg() before using the UL estimator\n");
return SRSLTE_ERROR;
}
int n_rs = srslte_refsignal_dmrs_N_rs(format, q->cell.cp);
int n_rs = srslte_refsignal_dmrs_N_rs(cfg->format, q->cell.cp);
if (!n_rs) {
fprintf(stderr, "Error computing N_rs\n");
ERROR("Error computing N_rs\n");
return SRSLTE_ERROR;
}
int nrefs_sf = SRSLTE_NRE * n_rs * 2;
/* Get references from the input signal */
srslte_refsignal_dmrs_pucch_get(&q->dmrs_signal, format, n_pucch, input, q->pilot_recv_signal);
srslte_refsignal_dmrs_pucch_get(&q->dmrs_signal, cfg, input, q->pilot_recv_signal);
/* Generate known pilots */
uint8_t pucch2_bits[2] = {0, 0};
if (format == SRSLTE_PUCCH_FORMAT_2A || format == SRSLTE_PUCCH_FORMAT_2B) {
if (cfg->format == SRSLTE_PUCCH_FORMAT_2A || cfg->format == SRSLTE_PUCCH_FORMAT_2B) {
float max = -1e9;
int i_max = 0;
int m = 0;
if (format == SRSLTE_PUCCH_FORMAT_2A) {
if (cfg->format == SRSLTE_PUCCH_FORMAT_2A) {
m = 2;
} else {
m = 4;
}
for (int i=0;i<m;i++) {
pucch2_bits[0] = i%2;
pucch2_bits[1] = i/2;
srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, format, n_pucch, sf_idx, pucch2_bits, q->pilot_known_signal);
cfg->pucch2_drs_bits[0] = i % 2;
cfg->pucch2_drs_bits[1] = i / 2;
srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, sf, cfg, q->pilot_known_signal);
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates_tmp[i], nrefs_sf);
float x = cabsf(srslte_vec_acc_cc(q->pilot_estimates_tmp[i], nrefs_sf));
if (x >= max) {
@ -350,20 +369,22 @@ int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, cf_t *input, cf_t *ce,
}
}
memcpy(q->pilot_estimates, q->pilot_estimates_tmp[i_max], nrefs_sf*sizeof(cf_t));
pucch2_ack_bits[0] = i_max%2;
pucch2_ack_bits[1] = i_max/2;
cfg->pucch2_drs_bits[0] = i_max % 2;
cfg->pucch2_drs_bits[1] = i_max / 2;
} else {
srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, format, n_pucch, sf_idx, pucch2_bits, q->pilot_known_signal);
srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, sf, cfg, q->pilot_known_signal);
/* Use the known DMRS signal to compute Least-squares estimates */
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates, nrefs_sf);
}
if (ce != NULL) {
if (res->ce != NULL) {
/* FIXME: Currently averaging entire slot, performance good enough? */
for (int ns = 0; ns < 2; ns++) {
// Average all slot
for (int i=1;i<n_rs;i++) {
srslte_vec_sum_ccc(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_estimates[(i+ns*n_rs)*SRSLTE_NRE],
srslte_vec_sum_ccc(&q->pilot_estimates[ns * n_rs * SRSLTE_NRE],
&q->pilot_estimates[(i + ns * n_rs) * SRSLTE_NRE],
&q->pilot_estimates[ns * n_rs * SRSLTE_NRE],
SRSLTE_NRE);
}
@ -376,12 +397,13 @@ int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, cf_t *input, cf_t *ce,
q->smooth_filter, SRSLTE_NRE, 1, q->smooth_filter_len);
// Determine n_prb
uint32_t n_prb = srslte_pucch_n_prb(&q->dmrs_signal.pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns);
uint32_t n_prb = srslte_pucch_n_prb(&q->cell, cfg, ns);
// copy estimates to slot
for (int i=0;i<SRSLTE_CP_NSYMB(q->cell.cp);i++) {
memcpy(&ce[SRSLTE_RE_IDX(q->cell.nof_prb, i+ns*SRSLTE_CP_NSYMB(q->cell.cp), n_prb*SRSLTE_NRE)],
&q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE], sizeof(cf_t)*SRSLTE_NRE);
memcpy(&res->ce[SRSLTE_RE_IDX(q->cell.nof_prb, i + ns * SRSLTE_CP_NSYMB(q->cell.cp), n_prb * SRSLTE_NRE)],
&q->pilot_recv_signal[ns * n_rs * SRSLTE_NRE],
sizeof(cf_t) * SRSLTE_NRE);
}
}
}
@ -389,12 +411,3 @@ int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, cf_t *input, cf_t *ce,
return 0;
}
float srslte_chest_ul_get_noise_estimate(srslte_chest_ul_t *q) {
return q->noise_estimate;
}
float srslte_chest_ul_get_snr(srslte_chest_ul_t *q) {
return q->pilot_power/srslte_chest_ul_get_noise_estimate(q);
}

@ -24,12 +24,12 @@
*
*/
#include "srslte/srslte.h"
#include <complex.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <complex.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/ch_estimation/refsignal_dl.h"
@ -37,6 +37,105 @@
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/common/sequence.h"
/** 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_NOF_SF_X_FRAME; i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb));
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_set_cell(srslte_refsignal_t* q, srslte_cell_t cell)
{
uint32_t c_init;
uint32_t N_cp, mp;
srslte_sequence_t seq;
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
q->cell = cell;
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;
}
srslte_dl_sf_cfg_t sf_cfg;
ZERO_OBJECT(sf_cfg);
for (uint32_t ns = 0; ns < SRSLTE_NSLOTS_X_FRAME; ns++) {
for (uint32_t p = 0; p < 2; p++) {
sf_cfg.tti = ns / 2;
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(q, &sf_cfg, 2 * p) / 2;
for (uint32_t 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 (uint32_t 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);
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */
void srslte_refsignal_free(srslte_refsignal_t* q)
{
for (int p = 0; p < 2; p++) {
for (int i = 0; i < SRSLTE_NOF_SF_X_FRAME; i++) {
if (q->pilots[p][i]) {
free(q->pilots[p][i]);
}
}
}
bzero(q, sizeof(srslte_refsignal_t));
}
uint32_t srslte_refsignal_cs_v(uint32_t port_id, uint32_t ref_symbol_idx)
{
uint32_t v = 0;
@ -73,27 +172,169 @@ uint32_t srslte_refsignal_cs_v(uint32_t port_id, uint32_t ref_symbol_idx)
return v;
}
uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id)
inline uint32_t srslte_refsignal_cs_nof_symbols(srslte_refsignal_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id)
{
uint32_t ret;
if (q->cell.frame_type == SRSLTE_FDD || !sf->tdd_config.configured ||
srslte_sfidx_tdd_type(sf->tdd_config, sf->tti % 10) == SRSLTE_TDD_SF_D) {
if (port_id < 2) {
ret = 4;
return 4;
} else {
ret = 2;
return 2;
}
return ret;
} else {
uint32_t nof_dw_symbols = srslte_sfidx_tdd_nof_dw(sf->tdd_config);
if (q->cell.cp == SRSLTE_CP_NORM) {
if (nof_dw_symbols >= 12) {
if (port_id < 2) {
return 4;
} else {
return 2;
}
uint32_t srslte_refsignal_mbsfn_nof_symbols()
{
} else if (nof_dw_symbols >= 9) {
if (port_id < 2) {
return 3;
} else {
return 2;
}
} else if (nof_dw_symbols >= 5) {
if (port_id < 2) {
return 2;
} else {
return 1;
}
} else {
return 1;
}
} else {
if (nof_dw_symbols >= 10) {
if (port_id < 2) {
return 4;
} else {
return 2;
}
} else if (nof_dw_symbols >= 8) {
if (port_id < 2) {
return 3;
} else {
return 2;
}
} else if (nof_dw_symbols >= 4) {
if (port_id < 2) {
return 2;
} else {
return 1;
}
} else {
return 1;
}
}
}
}
inline uint32_t srslte_refsignal_cs_nof_re(srslte_refsignal_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id)
{
return srslte_refsignal_cs_nof_symbols(q, sf, port_id) * q->cell.nof_prb * 2; // 2 RE per PRB
}
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_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t port_id)
{
if (port_id < 2) {
if (l % 2) {
return (l/2+1)*SRSLTE_CP_NSYMB(cp) - 3;
} else {
return (l/2)*SRSLTE_CP_NSYMB(cp);
}
} else {
return 1+l*SRSLTE_CP_NSYMB(cp);
}
}
/* Maps a reference signal initialized with srslte_refsignal_cs_init() into an array of subframe symbols */
int srslte_refsignal_cs_put_sf(srslte_refsignal_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id, cf_t* sf_symbols)
{
uint32_t i, l;
uint32_t fidx;
if (q != NULL && port_id < SRSLTE_MAX_PORTS && sf_symbols != NULL) {
cf_t* pilots = q->pilots[port_id / 2][sf->tti % 10];
for (l = 0; l < srslte_refsignal_cs_nof_symbols(q, sf, port_id); l++) {
uint32_t nsymbol = srslte_refsignal_cs_nsymbol(l, q->cell.cp, port_id);
/* Compute offset frequency index */
fidx = ((srslte_refsignal_cs_v(port_id, l) + (q->cell.id % 6)) % 6);
for (i = 0; i < 2 * q->cell.nof_prb; i++) {
sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, nsymbol, fidx)] = pilots[SRSLTE_REFSIGNAL_PILOT_IDX(i, l, q->cell)];
fidx += SRSLTE_NRE / 2; // 1 reference every 6 RE
}
}
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_refsignal_t* q, srslte_dl_sf_cfg_t* sf, uint32_t port_id, cf_t* sf_symbols, cf_t* pilots)
{
uint32_t i, l;
uint32_t fidx;
if (q != NULL && pilots != NULL && sf_symbols != NULL) {
for (l = 0; l < srslte_refsignal_cs_nof_symbols(q, sf, port_id); l++) {
uint32_t nsymbol = srslte_refsignal_cs_nsymbol(l, q->cell.cp, port_id);
/* Compute offset frequency index */
fidx = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0);
for (i = 0; i < 2 * q->cell.nof_prb; i++) {
pilots[SRSLTE_REFSIGNAL_PILOT_IDX(i, l, q->cell)] = sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, nsymbol, fidx)];
fidx += SRSLTE_NRE / 2; // 2 references per PRB
}
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
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;
}
}
uint32_t srslte_refsignal_mbsfn_nof_symbols()
{
return 3;
}
inline uint32_t srslte_refsignal_mbsfn_fidx(uint32_t l)
{
@ -108,19 +349,6 @@ inline uint32_t srslte_refsignal_mbsfn_fidx(uint32_t l)
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) {
return (l/2+1)*SRSLTE_CP_NSYMB(cp) - 3;
} else {
return (l/2)*SRSLTE_CP_NSYMB(cp);
}
} else {
return 1+l*SRSLTE_CP_NSYMB(cp);
}
}
inline uint32_t srslte_refsignal_mbsfn_nsymbol(uint32_t l)
{
uint32_t ret = 0;
@ -148,7 +376,7 @@ int srslte_refsignal_mbsfn_gen_seq(srslte_refsignal_t * q, srslte_cell_t cell, u
goto free_and_exit;
}
for(ns=0; ns<SRSLTE_NSUBFRAMES_X_FRAME;ns++){
for (ns = 0; ns < SRSLTE_NOF_SF_X_FRAME; ns++) {
for (p = 0; p < 2; p++) {
uint32_t nsymbols = 3; // replace with function
for(l=0;l<nsymbols;l++) {
@ -158,7 +386,9 @@ int srslte_refsignal_mbsfn_gen_seq(srslte_refsignal_t * q, srslte_cell_t cell, u
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);
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);
}
}
}
@ -173,7 +403,6 @@ free_and_exit:
srslte_refsignal_free(q);
}
return ret;
}
@ -188,9 +417,8 @@ int srslte_refsignal_mbsfn_init(srslte_refsignal_t * q, uint32_t max_prb)
q->type = SRSLTE_SF_MBSFN;
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
for (i = 0; i < SRSLTE_NOF_SF_X_FRAME; i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * max_prb * 18);
if (!q->pilots[p][i]) {
perror("malloc");
@ -199,7 +427,6 @@ int srslte_refsignal_mbsfn_init(srslte_refsignal_t * q, uint32_t max_prb)
}
}
ret = SRSLTE_SUCCESS;
}
@ -230,202 +457,6 @@ int srslte_refsignal_mbsfn_set_cell(srslte_refsignal_t * q, srslte_cell_t cell,
}
/** 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_set_cell(srslte_refsignal_t * q, srslte_cell_t cell)
{
uint32_t c_init;
uint32_t i, ns, l, p;
uint32_t N_cp, mp;
srslte_sequence_t seq;
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));
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);
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */
void srslte_refsignal_free(srslte_refsignal_t * q)
{
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_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)
{
uint32_t i, l;
uint32_t fidx;
if (srslte_cell_isvalid(&cell) &&
srslte_portid_isvalid(port_id) &&
pilots != NULL &&
sf_symbols != NULL)
{
for (l=0;l<srslte_refsignal_cs_nof_symbols(port_id);l++) {
uint32_t nsymbol = srslte_refsignal_cs_nsymbol(l, cell.cp, port_id);
/* Compute offset frequency index */
fidx = ((srslte_refsignal_cs_v(port_id, l) + (cell.id % 6)) % 6);
for (i = 0; i < 2*cell.nof_prb; i++) {
sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, nsymbol, fidx)] = pilots[SRSLTE_REFSIGNAL_PILOT_IDX(i,l,cell)];
fidx += SRSLTE_NRE/2; // 1 reference every 6 RE
}
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
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)
{
uint32_t i, l;
uint32_t fidx;
if (srslte_cell_isvalid(&cell) &&
srslte_portid_isvalid(port_id) &&
pilots != NULL &&
sf_symbols != NULL)
{
for (l=0;l<srslte_refsignal_cs_nof_symbols(port_id);l++) {
uint32_t nsymbol = srslte_refsignal_cs_nsymbol(l, cell.cp, port_id);
/* Compute offset frequency index */
fidx = srslte_refsignal_cs_fidx(cell, l, port_id, 0);
for (i = 0; i < 2*cell.nof_prb; i++) {
pilots[SRSLTE_REFSIGNAL_PILOT_IDX(i,l,cell)] = sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, nsymbol, fidx)];
fidx += SRSLTE_NRE/2; // 2 references per PRB
}
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
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;

@ -29,14 +29,14 @@
#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"
#include "srslte/phy/utils/vector.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/dft/dft_precoding.h"
#include "srslte/phy/phch/pucch.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#include "ul_rs_tables.h"
@ -216,9 +216,7 @@ int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t * q, srslte_cell_t cell)
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);
q->cell = cell;
// Precompute n_prs
if (generate_n_prs(q)) {
@ -244,27 +242,8 @@ int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t * q, srslte_cell_t cell)
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,
srslte_refsignal_srs_cfg_t *srs_cfg)
static uint32_t largest_prime_lower_than(uint32_t x)
{
if (pusch_cfg) {
memcpy(&q->pusch_cfg, pusch_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
}
if (pucch_cfg) {
if (srslte_pucch_cfg_isvalid(pucch_cfg, q->cell.nof_prb)) {
memcpy(&q->pucch_cfg, pucch_cfg, sizeof(srslte_pucch_cfg_t));
} else {
fprintf(stderr, "Invalid PUCCH configuration in refsignal_ul\n");
}
}
if (srs_cfg) {
memcpy(&q->srs_cfg, srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
}
}
uint32_t largest_prime_lower_than(uint32_t x) {
/* get largest prime n_zc<len */
for (uint32_t i = NOF_PRIME_NUMBERS - 1; i > 0; i--) {
if (prime_numbers[i] < x) {
@ -329,8 +308,8 @@ static float pusch_alpha(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_c
}
bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg,
uint32_t nof_prb) {
static bool pusch_cfg_isvalid(srslte_refsignal_ul_t* q, srslte_refsignal_dmrs_pusch_cfg_t* cfg, uint32_t nof_prb)
{
if (cfg->cyclic_shift < SRSLTE_NOF_CSHIFT &&
cfg->delta_ss < SRSLTE_NOF_DELTA_SS &&
nof_prb <= q->cell.nof_prb) {
@ -340,40 +319,55 @@ bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q, srslte_re
}
}
void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, cf_t *r_pusch, uint32_t nof_prb, uint32_t n_prb[2], cf_t *sf_symbols)
void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t* q,
srslte_pusch_cfg_t* pusch_cfg,
cf_t* r_pusch,
cf_t* sf_symbols)
{
for (uint32_t ns_idx=0;ns_idx<2;ns_idx++) {
INFO("Putting DRMS to n_prb: %d, L: %d, ns_idx: %d\n", n_prb[ns_idx], nof_prb, ns_idx);
INFO("Putting DMRS to n_prb: %d, L: %d, ns_idx: %d\n",
pusch_cfg->grant.n_prb_tilde[ns_idx],
pusch_cfg->grant.L_prb,
ns_idx);
uint32_t L = SRSLTE_REFSIGNAL_UL_L(ns_idx, q->cell.cp);
memcpy(&sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, L, n_prb[ns_idx]*SRSLTE_NRE)],
&r_pusch[ns_idx*SRSLTE_NRE*nof_prb], nof_prb*SRSLTE_NRE*sizeof(cf_t));
memcpy(&sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, L, pusch_cfg->grant.n_prb_tilde[ns_idx] * SRSLTE_NRE)],
&r_pusch[ns_idx * SRSLTE_NRE * pusch_cfg->grant.L_prb],
pusch_cfg->grant.L_prb * SRSLTE_NRE * sizeof(cf_t));
}
}
void srslte_refsignal_dmrs_pusch_get(srslte_refsignal_ul_t *q, cf_t *sf_symbols, uint32_t nof_prb, uint32_t n_prb[2], cf_t *r_pusch)
void srslte_refsignal_dmrs_pusch_get(srslte_refsignal_ul_t* q,
srslte_pusch_cfg_t* pusch_cfg,
cf_t* sf_symbols,
cf_t* r_pusch)
{
for (uint32_t ns_idx = 0; ns_idx < 2; ns_idx++) {
INFO("Getting DRMS from n_prb: %d, L: %d, ns_idx: %d\n", n_prb[ns_idx], nof_prb, ns_idx);
INFO("Getting DMRS from n_prb: %d, L: %d, ns_idx: %d\n",
pusch_cfg->grant.n_prb_tilde[ns_idx],
pusch_cfg->grant.L_prb,
ns_idx);
uint32_t L = SRSLTE_REFSIGNAL_UL_L(ns_idx, q->cell.cp);
memcpy(&r_pusch[ns_idx*SRSLTE_NRE*nof_prb],
&sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, L, n_prb[ns_idx]*SRSLTE_NRE)],
nof_prb*SRSLTE_NRE*sizeof(cf_t));
memcpy(&r_pusch[ns_idx * SRSLTE_NRE * pusch_cfg->grant.L_prb],
&sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, L, pusch_cfg->grant.n_prb_tilde[ns_idx] * SRSLTE_NRE)],
pusch_cfg->grant.L_prb * SRSLTE_NRE * sizeof(cf_t));
}
}
/* Computes r sequence */
void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t delta_ss) {
static void compute_r(
srslte_refsignal_ul_t* q, srslte_refsignal_dmrs_pusch_cfg_t* cfg, uint32_t nof_prb, uint32_t ns, uint32_t delta_ss)
{
// Get group hopping number u
uint32_t f_gh = 0;
if (q->pusch_cfg.group_hopping_en) {
if (cfg->group_hopping_en) {
f_gh = q->f_gh[ns];
}
uint32_t u = (f_gh + (q->cell.id%30)+delta_ss)%30;
// Get sequence hopping number v
uint32_t v = 0;
if (nof_prb >= 6 && q->pusch_cfg.sequence_hopping_en) {
v = q->v_pusch[ns][q->pusch_cfg.delta_ss];
if (nof_prb >= 6 && cfg->sequence_hopping_en) {
v = q->v_pusch[ns][cfg->delta_ss];
}
// Compute signal argument
@ -381,10 +375,9 @@ 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)
int srslte_refsignal_dmrs_pusch_pregen_init(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 sf_idx = 0; sf_idx < SRSLTE_NOF_SF_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]) {
@ -405,16 +398,17 @@ int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q, srslte_ref
return SRSLTE_SUCCESS;
}
int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen)
int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t* q,
srslte_refsignal_ul_dmrs_pregen_t* pregen,
srslte_refsignal_dmrs_pusch_cfg_t* cfg)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t sf_idx = 0; sf_idx < SRSLTE_NOF_SF_X_FRAME; sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=q->cell.nof_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) {
if (pregen->r[cs][sf_idx][n]) {
if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) {
if (srslte_refsignal_dmrs_pusch_gen(q, cfg, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) {
return SRSLTE_ERROR;
}
} else {
@ -432,7 +426,7 @@ int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsigna
void srslte_refsignal_dmrs_pusch_pregen_free(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 sf_idx = 0; sf_idx < SRSLTE_NOF_SF_X_FRAME; sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=q->cell.nof_prb;n++) {
@ -449,40 +443,42 @@ void srslte_refsignal_dmrs_pusch_pregen_free(srslte_refsignal_ul_t *q, srslte_re
}
int srslte_refsignal_dmrs_pusch_pregen_put(srslte_refsignal_ul_t* q,
srslte_ul_sf_cfg_t* sf_cfg,
srslte_refsignal_ul_dmrs_pregen_t* pregen,
uint32_t nof_prb,
uint32_t sf_idx,
uint32_t cyclic_shift_for_dmrs,
uint32_t n_prb[2],
srslte_pusch_cfg_t* pusch_cfg,
cf_t* sf_symbols)
{
if (srslte_dft_precoding_valid_prb(nof_prb) &&
sf_idx < SRSLTE_NSUBFRAMES_X_FRAME &&
cyclic_shift_for_dmrs < SRSLTE_NOF_CSHIFT)
{
srslte_refsignal_dmrs_pusch_put(q, pregen->r[cyclic_shift_for_dmrs][sf_idx][nof_prb], nof_prb, n_prb, sf_symbols);
uint32_t sf_idx = sf_cfg->tti % 10;
if (srslte_dft_precoding_valid_prb(pusch_cfg->grant.L_prb) && sf_idx < SRSLTE_NOF_SF_X_FRAME &&
pusch_cfg->grant.n_dmrs < SRSLTE_NOF_CSHIFT) {
srslte_refsignal_dmrs_pusch_put(
q, pusch_cfg, pregen->r[pusch_cfg->grant.n_dmrs][sf_idx][pusch_cfg->grant.L_prb], sf_symbols);
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
/* Generate DRMS for PUSCH signal according to 5.5.2.1 of 36.211 */
int srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t sf_idx,
uint32_t cyclic_shift_for_dmrs, cf_t *r_pusch)
/* Generate DMRS for PUSCH signal according to 5.5.2.1 of 36.211 */
int srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t* q,
srslte_refsignal_dmrs_pusch_cfg_t* cfg,
uint32_t nof_prb,
uint32_t sf_idx,
uint32_t cyclic_shift_for_dmrs,
cf_t* r_pusch)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (srslte_refsignal_dmrs_pusch_cfg_isvalid(q, &q->pusch_cfg, nof_prb)) {
if (pusch_cfg_isvalid(q, cfg, nof_prb)) {
ret = SRSLTE_ERROR;
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
compute_r(q, nof_prb, ns, q->pusch_cfg.delta_ss);
compute_r(q, cfg, nof_prb, ns, cfg->delta_ss);
// Add cyclic prefix alpha
float alpha = pusch_alpha(q, &q->pusch_cfg, cyclic_shift_for_dmrs, ns);
float alpha = pusch_alpha(q, cfg, cyclic_shift_for_dmrs, ns);
// Do complex exponential and adjust amplitude
for (int i=0;i<SRSLTE_NRE*nof_prb;i++) {
@ -506,6 +502,7 @@ uint32_t srslte_refsignal_dmrs_N_rs(srslte_pucch_format_t format, srslte_cp_t cp
return 2;
}
case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_3:
if (SRSLTE_CP_ISNORM(cp)) {
return 2;
} else {
@ -515,7 +512,7 @@ uint32_t srslte_refsignal_dmrs_N_rs(srslte_pucch_format_t format, srslte_cp_t cp
case SRSLTE_PUCCH_FORMAT_2B:
return 2;
default:
fprintf(stderr, "Unsupported format %d\n", format);
ERROR("DMRS Nof RS: Unsupported format %d\n", format);
return 0;
}
return 0;
@ -538,6 +535,7 @@ uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m, srslte_pucch_format_t fo
}
break;
case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_3:
if (SRSLTE_CP_ISNORM(cp)) {
if (m < 2) {
return pucch_dmrs_symbol_format2_cpnorm[m];
@ -555,31 +553,35 @@ uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m, srslte_pucch_format_t fo
}
break;
default:
fprintf(stderr, "Unsupported format %d\n", format);
ERROR("DMRS Symbol indexes: Unsupported format %d\n", format);
return 0;
}
return 0;
}
/* Generates DMRS for PUCCH according to 5.5.2.2 in 36.211 */
int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch,
uint32_t sf_idx, uint8_t pucch_bits[2], cf_t *r_pucch)
int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_pucch_cfg_t* cfg,
cf_t* r_pucch)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q && r_pucch) {
ret = SRSLTE_ERROR;
uint32_t N_rs=srslte_refsignal_dmrs_N_rs(format, q->cell.cp);
uint32_t N_rs = srslte_refsignal_dmrs_N_rs(cfg->format, q->cell.cp);
uint32_t sf_idx = sf->tti % 10;
cf_t z_m_1 = 1.0;
if (format == SRSLTE_PUCCH_FORMAT_2A || format == SRSLTE_PUCCH_FORMAT_2B) {
srslte_pucch_format2ab_mod_bits(format, pucch_bits, &z_m_1);
if (cfg->format == SRSLTE_PUCCH_FORMAT_2A || cfg->format == SRSLTE_PUCCH_FORMAT_2B) {
srslte_pucch_format2ab_mod_bits(cfg->format, cfg->pucch2_drs_bits, &z_m_1);
}
for (uint32_t ns = 2 * sf_idx; ns < 2 * (sf_idx + 1); ns++) {
// Get group hopping number u
uint32_t f_gh = 0;
if (q->pusch_cfg.group_hopping_en) {
if (cfg->group_hopping_en) {
f_gh = q->f_gh[ns];
}
uint32_t u = (f_gh + (q->cell.id % 30)) % 30;
@ -589,18 +591,18 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
for (uint32_t m=0;m<N_rs;m++) {
uint32_t n_oc = 0;
uint32_t l = srslte_refsignal_dmrs_pucch_symbol(m, format, q->cell.cp);
uint32_t l = srslte_refsignal_dmrs_pucch_symbol(m, cfg->format, q->cell.cp);
// Add cyclic prefix alpha
float alpha = 0.0;
if (format < SRSLTE_PUCCH_FORMAT_2) {
alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, NULL);
if (cfg->format < SRSLTE_PUCCH_FORMAT_2) {
alpha = srslte_pucch_alpha_format1(q->n_cs_cell, cfg, q->cell.cp, true, ns, l, &n_oc, NULL);
} else {
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l);
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, cfg, ns, l);
}
// Choose number of symbols and orthogonal sequence from Tables 5.5.2.2.1-1 to -3
float *w=NULL;
switch (format) {
switch (cfg->format) {
case SRSLTE_PUCCH_FORMAT_1:
case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B:
@ -611,6 +613,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
}
break;
case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_3:
if (SRSLTE_CP_ISNORM(q->cell.cp)) {
w=w_arg_pucch_format2_cpnorm;
} else {
@ -622,7 +625,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
w=w_arg_pucch_format2_cpnorm;
break;
default:
fprintf(stderr, "Unsupported format %d\n", format);
ERROR("DMRS Generator: Unsupported format %d\n", cfg->format);
return SRSLTE_ERROR;
}
cf_t z_m = 1.0;
@ -630,7 +633,8 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
z_m = z_m_1;
}
for (uint32_t n=0;n<SRSLTE_NRE;n++) {
r_pucch[(ns%2)*SRSLTE_NRE*N_rs+m*SRSLTE_NRE+n] = z_m*cexpf(I*(w[m]+q->tmp_arg[n]+alpha*n));
r_pucch[(ns % 2) * SRSLTE_NRE * N_rs + m * SRSLTE_NRE + n] =
z_m * cexpf(I * (w[m] + q->tmp_arg[n] + alpha * n));
}
}
}
@ -639,21 +643,22 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
return ret;
}
int srslte_refsignal_dmrs_pucch_cp(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *source, cf_t *dest, bool source_is_grid)
int srslte_refsignal_dmrs_pucch_cp(
srslte_refsignal_ul_t* q, srslte_pucch_cfg_t* cfg, cf_t* source, cf_t* dest, bool source_is_grid)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q && source && dest) {
ret = SRSLTE_ERROR;
uint32_t nsymbols = SRSLTE_CP_ISNORM(q->cell.cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB;
uint32_t N_rs = srslte_refsignal_dmrs_N_rs(format, q->cell.cp);
uint32_t N_rs = srslte_refsignal_dmrs_N_rs(cfg->format, q->cell.cp);
for (uint32_t ns=0;ns<2;ns++) {
// Determine n_prb
uint32_t n_prb = srslte_pucch_n_prb(&q->pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns);
uint32_t n_prb = srslte_pucch_n_prb(&q->cell, cfg, ns);
for (uint32_t i=0;i<N_rs;i++) {
uint32_t l = srslte_refsignal_dmrs_pucch_symbol(i, format, q->cell.cp);
uint32_t l = srslte_refsignal_dmrs_pucch_symbol(i, cfg->format, q->cell.cp);
if (!source_is_grid) {
memcpy(&dest[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
&source[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE],
@ -672,19 +677,19 @@ int srslte_refsignal_dmrs_pucch_cp(srslte_refsignal_ul_t *q, srslte_pucch_format
}
/* Maps PUCCH DMRS to the physical resources as defined in 5.5.2.2.2 in 36.211 */
int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *r_pucch, cf_t *output)
int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q, srslte_pucch_cfg_t* cfg, cf_t* r_pucch, cf_t* output)
{
return srslte_refsignal_dmrs_pucch_cp(q, format, n_pucch, r_pucch, output, false);
return srslte_refsignal_dmrs_pucch_cp(q, cfg, r_pucch, output, false);
}
/* Gets PUCCH DMRS from the physical resources as defined in 5.5.2.2.2 in 36.211 */
int srslte_refsignal_dmrs_pucch_get(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *input, cf_t *r_pucch)
int srslte_refsignal_dmrs_pucch_get(srslte_refsignal_ul_t* q, srslte_pucch_cfg_t* cfg, cf_t* input, cf_t* r_pucch)
{
return srslte_refsignal_dmrs_pucch_cp(q, format, n_pucch, input, r_pucch, true);
return srslte_refsignal_dmrs_pucch_cp(q, cfg, input, r_pucch, true);
}
uint32_t T_srs_table(uint32_t I_srs) {
static uint32_t T_srs_table(uint32_t I_srs)
{
uint32_t T_srs;
/* This is Table 8.2-1 */
if (I_srs < 2) {
@ -746,6 +751,73 @@ int srslte_refsignal_srs_send_ue(uint32_t I_srs, uint32_t tti) {
}
}
// Shortened PUCCH happen in every cell-specific SRS subframes for Format 1/1a/1b
void srslte_refsignal_srs_pucch_shortened(srslte_refsignal_ul_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_refsignal_srs_cfg_t* srs_cfg,
srslte_pucch_cfg_t* pucch_cfg)
{
bool shortened = false;
if (srs_cfg->configured && pucch_cfg->format < SRSLTE_PUCCH_FORMAT_2) {
shortened = false;
// If CQI is not transmitted, PUCCH will be normal unless ACK/NACK and SRS simultaneous transmission is enabled
if (srs_cfg->simul_ack) {
// If simultaneous ACK and SRS is enabled, PUCCH is shortened in cell-specific SRS subframes
if (srslte_refsignal_srs_send_cs(srs_cfg->subframe_config, sf->tti % 10) == 1) {
shortened = true;
}
}
}
sf->shortened = shortened;
}
void srslte_refsignal_srs_pusch_shortened(srslte_refsignal_ul_t* q,
srslte_ul_sf_cfg_t* sf,
srslte_refsignal_srs_cfg_t* srs_cfg,
srslte_pusch_cfg_t* pusch_cfg)
{
bool shortened = false;
if (srs_cfg->configured) {
// If UE-specific SRS is configured, PUSCH is shortened every time UE transmits SRS even if overlaping in the same
// RB or not
if (srslte_refsignal_srs_send_cs(srs_cfg->subframe_config, sf->tti % 10) == 1 &&
srslte_refsignal_srs_send_ue(srs_cfg->I_srs, sf->tti) == 1) {
shortened = true;
/* If RBs are contiguous, PUSCH is not shortened */
uint32_t k0_srs = srslte_refsignal_srs_rb_start_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
uint32_t nrb_srs = srslte_refsignal_srs_rb_L_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
for (uint32_t ns = 0; ns < 2 && shortened; ns++) {
if (pusch_cfg->grant.n_prb_tilde[ns] ==
k0_srs + nrb_srs || // If PUSCH is contiguous on the right-hand side of SRS
pusch_cfg->grant.n_prb_tilde[ns] + pusch_cfg->grant.L_prb ==
k0_srs) // If SRS is contiguous on the left-hand side of PUSCH
{
shortened = false;
}
}
}
// If not coincides with UE transmission. PUSCH shall be shortened if cell-specific SRS transmission RB
// coincides with PUSCH allocated RB
if (!shortened) {
if (srslte_refsignal_srs_send_cs(srs_cfg->subframe_config, sf->tti % 10) == 1) {
uint32_t k0_srs = srslte_refsignal_srs_rb_start_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
uint32_t nrb_srs = srslte_refsignal_srs_rb_L_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
for (uint32_t ns = 0; ns < 2 && !shortened; ns++) {
if ((pusch_cfg->grant.n_prb_tilde[ns] >= k0_srs && pusch_cfg->grant.n_prb_tilde[ns] < k0_srs + nrb_srs) ||
(pusch_cfg->grant.n_prb_tilde[ns] + pusch_cfg->grant.L_prb >= k0_srs &&
pusch_cfg->grant.n_prb_tilde[ns] + pusch_cfg->grant.L_prb < k0_srs + nrb_srs) ||
(pusch_cfg->grant.n_prb_tilde[ns] <= k0_srs &&
pusch_cfg->grant.n_prb_tilde[ns] + pusch_cfg->grant.L_prb >= k0_srs + nrb_srs)) {
shortened = true;
}
}
}
}
}
sf->shortened = shortened;
}
/* Returns 1 if sf_idx is a valid subframe for SRS transmission according to subframe_config (cell-specific),
* as defined in Section 5.5.3.3 of 36.211. Returns 0 if no SRS shall be transmitted or a negative
* number if error.
@ -797,7 +869,8 @@ int srslte_refsignal_srs_send_cs(uint32_t subframe_config, uint32_t sf_idx) {
}
}
uint32_t srsbwtable_idx(uint32_t nof_prb) {
static uint32_t srsbwtable_idx(uint32_t nof_prb)
{
if (nof_prb <= 40) {
return 0;
} else if (nof_prb <= 60) {
@ -825,7 +898,8 @@ uint32_t srslte_refsignal_srs_rb_L_cs(uint32_t bw_cfg, uint32_t nof_prb) {
return 0;
}
uint32_t srs_Fb(srslte_refsignal_srs_cfg_t *cfg, uint32_t b, uint32_t nof_prb, uint32_t tti) {
static uint32_t srs_Fb(srslte_refsignal_srs_cfg_t* cfg, uint32_t b, uint32_t nof_prb, uint32_t tti)
{
uint32_t Fb = 0;
uint32_t T = T_srs_table(cfg->I_srs);
if (T) {
@ -847,7 +921,8 @@ uint32_t srs_Fb(srslte_refsignal_srs_cfg_t *cfg, uint32_t b, uint32_t nof_prb, u
}
/* Returns k0: frequency-domain starting position for ue-specific SRS */
uint32_t srs_k0_ue(srslte_refsignal_srs_cfg_t *cfg, uint32_t nof_prb, uint32_t tti) {
static uint32_t srs_k0_ue(srslte_refsignal_srs_cfg_t* cfg, uint32_t nof_prb, uint32_t tti)
{
if (cfg->bw_cfg < 8 && cfg->B < 4 && cfg->k_tc < 2) {
uint32_t k0p = srslte_refsignal_srs_rb_start_cs(cfg->bw_cfg, nof_prb) * SRSLTE_NRE + cfg->k_tc;
@ -870,17 +945,21 @@ uint32_t srs_k0_ue(srslte_refsignal_srs_cfg_t *cfg, uint32_t nof_prb, uint32_t t
return 0;
}
uint32_t srslte_refsignal_srs_M_sc(srslte_refsignal_ul_t *q) {
return m_srs_b[srsbwtable_idx(q->cell.nof_prb)][q->srs_cfg.B][q->srs_cfg.bw_cfg]*SRSLTE_NRE/2;
uint32_t srslte_refsignal_srs_M_sc(srslte_refsignal_ul_t* q, srslte_refsignal_srs_cfg_t* cfg)
{
return m_srs_b[srsbwtable_idx(q->cell.nof_prb)][cfg->B][cfg->bw_cfg] * SRSLTE_NRE / 2;
}
int srslte_refsignal_srs_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_srs_pregen_t *pregen)
int srslte_refsignal_srs_pregen(srslte_refsignal_ul_t* q,
srslte_refsignal_srs_pregen_t* pregen,
srslte_refsignal_srs_cfg_t* cfg,
srslte_refsignal_dmrs_pusch_cfg_t* dmrs)
{
uint32_t M_sc = srslte_refsignal_srs_M_sc(q);
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
uint32_t M_sc = srslte_refsignal_srs_M_sc(q, cfg);
for (uint32_t sf_idx = 0; sf_idx < SRSLTE_NOF_SF_X_FRAME; sf_idx++) {
pregen->r[sf_idx] = srslte_vec_malloc(2*M_sc*sizeof(cf_t));
if (pregen->r[sf_idx]) {
if (srslte_refsignal_srs_gen(q, sf_idx, pregen->r[sf_idx])) {
if (srslte_refsignal_srs_gen(q, cfg, dmrs, sf_idx, pregen->r[sf_idx])) {
return SRSLTE_ERROR;
}
} else {
@ -892,32 +971,39 @@ int srslte_refsignal_srs_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_srs_p
void srslte_refsignal_srs_pregen_free(srslte_refsignal_ul_t *q, srslte_refsignal_srs_pregen_t *pregen)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t sf_idx = 0; sf_idx < SRSLTE_NOF_SF_X_FRAME; sf_idx++) {
if (pregen->r[sf_idx]) {
free(pregen->r[sf_idx]);
}
}
}
int srslte_refsignal_srs_pregen_put(srslte_refsignal_ul_t *q, srslte_refsignal_srs_pregen_t *pregen,
uint32_t tti, cf_t *sf_symbols)
int srslte_refsignal_srs_pregen_put(srslte_refsignal_ul_t* q,
srslte_refsignal_srs_pregen_t* pregen,
srslte_refsignal_srs_cfg_t* cfg,
uint32_t tti,
cf_t* sf_symbols)
{
return srslte_refsignal_srs_put(q, tti, pregen->r[tti%SRSLTE_NSUBFRAMES_X_FRAME], sf_symbols);
return srslte_refsignal_srs_put(q, cfg, tti, pregen->r[tti % SRSLTE_NOF_SF_X_FRAME], sf_symbols);
}
/* Genearte SRS signal as defined in Section 5.5.3.1 */
int srslte_refsignal_srs_gen(srslte_refsignal_ul_t *q, uint32_t sf_idx, cf_t *r_srs)
int srslte_refsignal_srs_gen(srslte_refsignal_ul_t* q,
srslte_refsignal_srs_cfg_t* cfg,
srslte_refsignal_dmrs_pusch_cfg_t* pusch_cfg,
uint32_t sf_idx,
cf_t* r_srs)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (r_srs && q) {
if (r_srs && q && cfg && pusch_cfg) {
ret = SRSLTE_ERROR;
uint32_t M_sc = srslte_refsignal_srs_M_sc(q);
uint32_t M_sc = srslte_refsignal_srs_M_sc(q, cfg);
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
compute_r(q, M_sc/SRSLTE_NRE, ns, 0);
float alpha = 2*M_PI*q->srs_cfg.n_srs/8;
compute_r(q, pusch_cfg, M_sc / SRSLTE_NRE, ns, 0);
float alpha = 2 * M_PI * cfg->n_srs / 8;
// Do complex exponential and adjust amplitude
for (int i=0;i<M_sc;i++) {
@ -929,13 +1015,13 @@ int srslte_refsignal_srs_gen(srslte_refsignal_ul_t *q, uint32_t sf_idx, cf_t *r_
return ret;
}
int srslte_refsignal_srs_put(srslte_refsignal_ul_t *q, uint32_t tti, cf_t *r_srs, cf_t *sf_symbols) {
int srslte_refsignal_srs_put(
srslte_refsignal_ul_t* q, srslte_refsignal_srs_cfg_t* cfg, uint32_t tti, cf_t* r_srs, cf_t* sf_symbols)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (r_srs && q) {
ret = SRSLTE_ERROR;
uint32_t M_sc = srslte_refsignal_srs_M_sc(q);
uint32_t k0 = srs_k0_ue(&q->srs_cfg, q->cell.nof_prb, tti);
uint32_t M_sc = srslte_refsignal_srs_M_sc(q, cfg);
uint32_t k0 = srs_k0_ue(cfg, q->cell.nof_prb, tti);
for (int i=0;i<M_sc;i++) {
sf_symbols[SRSLTE_RE_IDX(q->cell.nof_prb, 2*SRSLTE_CP_NSYMB(q->cell.cp)-1, k0 + 2*i)] = r_srs[i];
}

@ -29,18 +29,16 @@
#include <strings.h>
#include <unistd.h>
#include <complex.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/srslte.h"
srslte_cell_t cell = {
6, // nof_prb
srslte_cell_t cell = {6, // nof_prb
1, // nof_ports
1000, // cell_id
SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_NORM,
SRSLTE_PHICH_R_1_6
};
SRSLTE_PHICH_R_1_6,
SRSLTE_FDD};
char *output_matlab = NULL;
@ -86,7 +84,7 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) {
srslte_chest_dl_t est;
cf_t *input = NULL, *ce = NULL, *h = NULL, *output = NULL;
int i, j, n_port=0, sf_idx=0, cid=0, num_re;
int i, j, num_re;
int ret = -1;
int max_cid;
FILE *fmatlab = NULL;
@ -124,6 +122,7 @@ int main(int argc, char **argv) {
goto do_exit;
}
uint32_t cid = 0;
if (cell.id == 1000) {
cid = 0;
max_cid = 504;
@ -131,19 +130,23 @@ 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");
if (srslte_chest_dl_init(&est, cell.nof_prb, 1)) {
ERROR("Error initializing equalizer\n");
goto do_exit;
}
while(cid <= max_cid) {
cell.id = cid;
if (srslte_chest_dl_set_cell(&est, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
ERROR("Error initializing equalizer\n");
goto do_exit;
}
for (sf_idx=0;sf_idx<1;sf_idx++) {
for (n_port=0;n_port<cell.nof_ports;n_port++) {
for (uint32_t sf_idx = 0; sf_idx < 1; sf_idx++) {
srslte_dl_sf_cfg_t sf_cfg;
ZERO_OBJECT(sf_cfg);
sf_cfg.tti = sf_idx;
for (uint32_t n_port = 0; n_port < cell.nof_ports; n_port++) {
bzero(input, sizeof(cf_t) * num_re);
for (i = 0; i < num_re; i++) {
@ -153,8 +156,7 @@ int main(int argc, char **argv) {
bzero(ce, sizeof(cf_t) * num_re);
bzero(h, sizeof(cf_t) * num_re);
srslte_refsignal_cs_put_sf(cell, n_port,
est.csr_refs.pilots[n_port/2][sf_idx], input);
srslte_refsignal_cs_put_sf(&est.csr_refs, &sf_cfg, n_port, input);
for (i = 0; i < 2 * SRSLTE_CP_NSYMB(cell.cp); i++) {
for (j = 0; j < cell.nof_prb * SRSLTE_NRE; j++) {
@ -163,11 +165,19 @@ int main(int argc, char **argv) {
input[i * cell.nof_prb * SRSLTE_NRE + j] *= h[i * cell.nof_prb * SRSLTE_NRE + j];
}
}
}
srslte_chest_dl_res_t res;
res.ce[0][0] = ce;
cf_t* input_m[SRSLTE_MAX_PORTS];
input_m[0] = input;
struct timeval t[3];
gettimeofday(&t[1], NULL);
for (int j = 0; j < 100; j++) {
srslte_chest_dl_estimate_port(&est, input, ce, sf_idx, n_port, 0);
srslte_chest_dl_estimate(&est, &sf_cfg, input_m, &res);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
@ -190,7 +200,7 @@ int main(int argc, char **argv) {
gettimeofday(&t[1], NULL);
for (int j = 0; j < 100; j++) {
srslte_predecoding_single(input, ce, output, NULL, num_re, 1.0f, srslte_chest_dl_get_noise_estimate(&est));
srslte_predecoding_single(input, ce, output, NULL, num_re, 1.0f, res.noise_estimate);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
@ -219,7 +229,6 @@ int main(int argc, char **argv) {
fprintf(fmatlab, ";\n");
}
}
}
cid += 10;
INFO("cid=%d\n", cid);
}
@ -246,7 +255,7 @@ do_exit:
if (!ret) {
printf("OK\n");
} else {
printf("Error at cid=%d, slot=%d, port=%d\n",cid, sf_idx, n_port);
printf("Error at cid=%d\n", cid);
}
exit(ret);

@ -1,159 +0,0 @@
/**
*
* \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 <string.h>
#include "srslte/srslte.h"
#include "srslte/mex/mexutils.h"
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define ENBCFG prhs[0]
#define INPUT prhs[1]
#define NOF_INPUTS 2
void help()
{
mexErrMsgTxt
("[estChannel, noiseEst, eq_output] = srslte_chest_dl(enb, inputSignal, [w_coeff])\n");
}
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int i;
srslte_cell_t cell;
srslte_chest_dl_t chest;
cf_t *input_signal = NULL, *output_signal = NULL, *tmp_x[SRSLTE_MAX_LAYERS];
cf_t *ce[SRSLTE_MAX_PORTS];
for (int i=0;i<SRSLTE_MAX_LAYERS;i++) {
tmp_x[i] = NULL;
}
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = NULL;
}
if (nrhs < NOF_INPUTS) {
help();
return;
}
if (mexutils_read_cell(ENBCFG, &cell)) {
help();
return;
}
uint32_t sf_idx=0;
if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &sf_idx)) {
help();
return;
}
if (srslte_chest_dl_init(&chest, cell)) {
mexErrMsgTxt("Error initiating channel estimator\n");
return;
}
/** Allocate input buffers */
int nof_re = 2*SRSLTE_CP_NSYMB(cell.cp)*cell.nof_prb*SRSLTE_NRE;
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = srslte_vec_malloc(nof_re * sizeof(cf_t));
}
for (i=0;i<SRSLTE_MAX_LAYERS;i++) {
tmp_x[i] = srslte_vec_malloc(nof_re * sizeof(cf_t));
}
output_signal = srslte_vec_malloc(nof_re * sizeof(cf_t));
// Read input signal
int insignal_len = mexutils_read_cf(INPUT, &input_signal);
if (insignal_len < 0) {
mexErrMsgTxt("Error reading input signal\n");
return;
}
// Read optional value smooth filter coefficient
if (nrhs > NOF_INPUTS) {
float w = (float) mxGetScalar(prhs[NOF_INPUTS]);
srslte_chest_dl_set_smooth_filter3_coeff(&chest, w);
} else {
srslte_chest_dl_set_smooth_filter(&chest, NULL, 0);
}
// Perform channel estimation
if (srslte_chest_dl_estimate(&chest, input_signal, ce, sf_idx)) {
mexErrMsgTxt("Error running channel estimator\n");
return;
}
// Get noise power estimation
float noise_power = srslte_chest_dl_get_noise_estimate(&chest);
// Perform channel equalization
if (cell.nof_ports == 1) {
srslte_predecoding_single(input_signal, ce[0], output_signal, nof_re, noise_power);
} else {
srslte_predecoding_diversity(input_signal, ce, tmp_x, cell.nof_ports, nof_re);
srslte_layerdemap_diversity(tmp_x, output_signal, cell.nof_ports, nof_re/cell.nof_ports);
}
/* Write output values */
if (nlhs >= 1) {
mexutils_write_cf(ce[0], &plhs[0], mxGetM(INPUT), mxGetN(INPUT));
}
if (nlhs >= 2) {
plhs[1] = mxCreateLogicalScalar(noise_power);
}
if (nlhs >= 3) {
mexutils_write_cf(output_signal, &plhs[2], mxGetM(INPUT), mxGetN(INPUT));
}
// Free all memory
srslte_chest_dl_free(&chest);
for (i=0;i<SRSLTE_MAX_LAYERS;i++) {
if (tmp_x[i]) {
free(tmp_x[i]);
}
}
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
if (ce[i]) {
free(ce[i]);
}
}
if (input_signal) {
free(input_signal);
}
if (output_signal) {
free(output_signal);
}
return;
}

@ -35,10 +35,12 @@
srslte_cell_t cell = {
6, // nof_prb
1, // nof_ports
0,
1000, // cell_id
SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_NORM
SRSLTE_PHICH_NORM,
SRSLTE_PHICH_R_1, // PHICH length
SRSLTE_FDD,
};
char *output_matlab = NULL;
@ -128,13 +130,13 @@ int main(int argc, char **argv) {
}
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");
ERROR("Error initializing equalizer\n");
goto do_exit;
}
while(cid <= max_cid) {
cell.id = cid;
if (srslte_chest_ul_set_cell(&est, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
ERROR("Error initializing equalizer\n");
goto do_exit;
}
@ -165,7 +167,7 @@ int main(int argc, char **argv) {
}
pusch_cfg.group_hopping_en = group_hopping_en;
pusch_cfg.sequence_hopping_en = sequence_hopping_en;
srslte_chest_ul_set_cfg(&est, &pusch_cfg, NULL, NULL);
srslte_chest_ul_pregen(&est, &pusch_cfg);
// Loop through subframe idx and cyclic shifts
@ -196,9 +198,23 @@ int main(int argc, char **argv) {
}
}
// Configure estimator
srslte_chest_ul_res_t res;
srslte_pusch_cfg_t cfg;
ZERO_OBJECT(cfg);
res.ce = ce;
cfg.grant.L_prb = n;
cfg.grant.n_prb_tilde[0] = 0;
cfg.grant.n_prb_tilde[1] = 0;
cfg.grant.n_dmrs = cshift_dmrs;
srslte_ul_sf_cfg_t ul_sf;
ZERO_OBJECT(ul_sf);
ul_sf.tti = sf_idx;
// Estimate channel
uint32_t prb_idx[2]= {0, 0};
srslte_chest_ul_estimate(&est, input, ce, n, sf_idx, cshift_dmrs, prb_idx);
srslte_chest_ul_estimate_pusch(&est, &ul_sf, &cfg, input, &res);
// Compute MSE
float mse = 0;

@ -1,181 +0,0 @@
/**
*
* \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 <string.h>
#include "srslte/srslte.h"
#include "srslte/mex/mexutils.h"
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define UECFG prhs[0]
#define PUSCHCFG prhs[1]
#define INPUT prhs[2]
#define NOF_INPUTS 3
void help()
{
mexErrMsgTxt
("[estChannel, noiseEst, eq_output] = srslte_chest_ul(ue_cfg, pusch_cfg, inputSignal, [w_coeff])\n");
}
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
srslte_cell_t cell;
srslte_chest_ul_t chest;
cf_t *input_signal = NULL, *output_signal = NULL;
cf_t *ce = NULL;
if (nrhs < NOF_INPUTS) {
help();
return;
}
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
}
if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
}
cell.cp = SRSLTE_CP_NORM;
cell.nof_ports = 1;
uint32_t sf_idx=0;
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
help();
return;
}
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
pusch_cfg.group_hopping_en = false;
pusch_cfg.sequence_hopping_en = false;
char *tmp = mexutils_get_char_struct(UECFG, "Hopping");
if (tmp) {
if (!strcmp(tmp, "Group")) {
pusch_cfg.group_hopping_en = true;
} else if (!strcmp(tmp, "Sequence")) {
pusch_cfg.sequence_hopping_en = true;
}
mxFree(tmp);
}
if (mexutils_read_uint32_struct(UECFG, "SeqGroup", &pusch_cfg.delta_ss)) {
pusch_cfg.delta_ss = 0;
}
if (mexutils_read_uint32_struct(UECFG, "CyclicShift", &pusch_cfg.cyclic_shift)) {
pusch_cfg.cyclic_shift = 0;
}
float *prbset;
mxArray *p;
p = mxGetField(PUSCHCFG, 0, "PRBSet");
if (!p) {
mexErrMsgTxt("Error field PRBSet not found in PUSCH config\n");
return;
}
uint32_t nof_prb = mexutils_read_f(p, &prbset);
uint32_t n_prb[2];
n_prb[0] = prbset[0];
n_prb[1] = prbset[0];
uint32_t cyclic_shift_for_dmrs = 0;
if (mexutils_read_uint32_struct(PUSCHCFG, "DynCyclicShift", &cyclic_shift_for_dmrs)) {
cyclic_shift_for_dmrs = 0;
}
if (srslte_chest_ul_init(&chest, cell)) {
mexErrMsgTxt("Error initiating channel estimator\n");
return;
}
srslte_chest_ul_set_cfg(&chest, &pusch_cfg, NULL, NULL);
/** Allocate input buffers */
int nof_re = 2*SRSLTE_CP_NSYMB(cell.cp)*cell.nof_prb*SRSLTE_NRE;
ce = srslte_vec_malloc(nof_re * sizeof(cf_t));
output_signal = srslte_vec_malloc(nof_re * sizeof(cf_t));
// Read input signal
int insignal_len = mexutils_read_cf(INPUT, &input_signal);
if (insignal_len < 0) {
mexErrMsgTxt("Error reading input signal\n");
return;
}
// Read optional value smooth filter coefficient
if (nrhs > NOF_INPUTS) {
float w = (float) mxGetScalar(prhs[NOF_INPUTS]);
srslte_chest_ul_set_smooth_filter3_coeff(&chest, w);
} else {
srslte_chest_ul_set_smooth_filter(&chest, NULL, 0);
}
// Perform channel estimation
if (srslte_chest_ul_estimate(&chest, input_signal, ce, nof_prb, sf_idx, cyclic_shift_for_dmrs, n_prb)) {
mexErrMsgTxt("Error running channel estimator\n");
return;
}
// Get noise power estimation
float noise_power = srslte_chest_ul_get_noise_estimate(&chest);
// Perform channel equalization
srslte_predecoding_single(input_signal, ce, output_signal, nof_re, noise_power);
/* Write output values */
if (nlhs >= 1) {
mexutils_write_cf(ce, &plhs[0], mxGetM(INPUT), mxGetN(INPUT));
}
if (nlhs >= 2) {
plhs[1] = mxCreateDoubleScalar(noise_power);
}
if (nlhs >= 3) {
mexutils_write_cf(output_signal, &plhs[2], mxGetM(INPUT), mxGetN(INPUT));
}
// Free all memory
srslte_chest_ul_free(&chest);
if (ce) {
free(ce);
}
if (input_signal) {
free(input_signal);
}
if (output_signal) {
free(output_signal);
}
return;
}

@ -1,151 +0,0 @@
/**
*
* \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 <string.h>
#include "srslte/srslte.h"
#include "srslte/mex/mexutils.h"
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define UECFG prhs[0]
#define PUSCHCFG prhs[1]
#define NOF_INPUTS 2
void help()
{
mexErrMsgTxt
("[seq] = srslte_refsignal_pusch(ueConfig, puschConfig)\n\n");
}
extern int indices[2048];
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
srslte_cell_t cell;
srslte_refsignal_ul_t refs;
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
uint32_t sf_idx;
if (nrhs != NOF_INPUTS) {
help();
return;
}
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
}
if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
}
cell.cp = SRSLTE_CP_NORM;
cell.nof_ports = 1;
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
mexErrMsgTxt("Field NSubframe not found in UE config\n");
return;
}
bzero(&pusch_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
pusch_cfg.group_hopping_en = false;
pusch_cfg.sequence_hopping_en = false;
char *tmp = mexutils_get_char_struct(UECFG, "Hopping");
if (tmp) {
if (!strcmp(tmp, "Group")) {
pusch_cfg.group_hopping_en = true;
} else if (!strcmp(tmp, "Sequence")) {
pusch_cfg.sequence_hopping_en = true;
}
mxFree(tmp);
}
if (mexutils_read_uint32_struct(UECFG, "SeqGroup", &pusch_cfg.delta_ss)) {
pusch_cfg.delta_ss = 0;
}
if (mexutils_read_uint32_struct(UECFG, "CyclicShift", &pusch_cfg.cyclic_shift)) {
pusch_cfg.cyclic_shift = 0;
}
float *prbset;
mxArray *p;
p = mxGetField(PUSCHCFG, 0, "PRBSet");
if (!p) {
mexErrMsgTxt("Error field PRBSet not found in PUSCH config\n");
return;
}
uint32_t nof_prb = mexutils_read_f(p, &prbset);
uint32_t cyclic_shift_for_dmrs = 0;
if (mexutils_read_uint32_struct(PUSCHCFG, "DynCyclicShift", &cyclic_shift_for_dmrs)) {
cyclic_shift_for_dmrs = 0;
}
if (srslte_refsignal_ul_init(&refs, cell)) {
mexErrMsgTxt("Error initiating srslte_refsignal_ul\n");
return;
}
mexPrintf("nof_prb: %d, ",nof_prb);
mexPrintf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift);
mexPrintf("cyclic_shift_for_dmrs: %d, ", cyclic_shift_for_dmrs);
mexPrintf("delta_ss: %d, ",pusch_cfg.delta_ss);
cf_t *signal = srslte_vec_malloc(2*SRSLTE_NRE*nof_prb*sizeof(cf_t));
if (!signal) {
perror("malloc");
return;
}
cf_t *sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t));
if (!sf_symbols) {
perror("malloc");
return;
}
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t));
srslte_refsignal_ul_set_cfg(&refs, &pusch_cfg, NULL, NULL);
//mexPrintf("Generating DRMS for ns=%d, nof_prb=%d\n", 2*sf_idx+i,pusch_cfg.nof_prb);
srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, cyclic_shift_for_dmrs, signal);
uint32_t n_prb[2];
n_prb[0] = prbset[0];
n_prb[1] = prbset[0];
srslte_refsignal_dmrs_pusch_put(&refs, signal, nof_prb, n_prb, sf_symbols);
if (nlhs >= 1) {
mexutils_write_cf(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
}
srslte_refsignal_ul_free(&refs);
free(signal);
free(prbset);
return;
}

@ -1,165 +0,0 @@
/**
*
* \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 <string.h>
#include "srslte/srslte.h"
#include "srslte/mex/mexutils.h"
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define UECFG prhs[0]
#define SRSCFG prhs[1]
#define NOF_INPUTS 2
void help()
{
mexErrMsgTxt
("[sym, subframe]=srslte_refsignal_srs(ue, chs)\n\n");
}
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nrhs != NOF_INPUTS) {
help();
return;
}
srslte_cell_t cell;
bzero(&cell, sizeof(srslte_cell_t));
cell.nof_ports = 1;
cell.cp = SRSLTE_CP_NORM;
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
}
if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) {
mexErrMsgTxt("Field NULRB not found in UE config\n");
return;
}
uint32_t sf_idx = 0;
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
mexErrMsgTxt("Field NSubframe not found in UE config\n");
return;
}
uint32_t nf = 0;
if (mexutils_read_uint32_struct(UECFG, "NFrame", &nf)) {
mexErrMsgTxt("Field NFrame not found in UE config\n");
return;
}
uint32_t tti = nf*10+sf_idx;
srslte_refsignal_srs_cfg_t srs_cfg;
bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
if (mexutils_read_uint32_struct(SRSCFG, "BWConfig", &srs_cfg.bw_cfg)) {
mexErrMsgTxt("Field BWConfig not found in SRSCFG\n");
return;
}
if (mexutils_read_uint32_struct(SRSCFG, "BW", &srs_cfg.B)) {
mexErrMsgTxt("Field BW not found in SRSCFG\n");
return;
}
if (mexutils_read_uint32_struct(SRSCFG, "ConfigIdx", &srs_cfg.I_srs)) {
mexErrMsgTxt("Field ConfigIdx not found in SRSCFG\n");
return;
}
if (mexutils_read_uint32_struct(SRSCFG, "FreqPosition", &srs_cfg.n_rrc)) {
mexErrMsgTxt("Field FreqPosition not found in SRSCFG\n");
return;
}
if (mexutils_read_uint32_struct(SRSCFG, "HoppingBW", &srs_cfg.b_hop)) {
mexErrMsgTxt("Field HoppingBW not found in SRSCFG\n");
return;
}
if (mexutils_read_uint32_struct(SRSCFG, "TxComb", &srs_cfg.k_tc)) {
mexErrMsgTxt("Field TxComb not found in SRSCFG\n");
return;
}
if (mexutils_read_uint32_struct(SRSCFG, "CyclicShift", &srs_cfg.n_srs)) {
mexErrMsgTxt("Field CyclicShift not found in SRSCFG\n");
return;
}
bool group_hopping_en = false;
char *hop = mexutils_get_char_struct(UECFG, "Hopping");
if (hop) {
if (!strcmp(hop, "Group")) {
group_hopping_en = true;
}
mxFree(hop);
}
cf_t *r_srs = srslte_vec_malloc(sizeof(cf_t) * cell.nof_prb * 12);
if (!r_srs) {
return;
}
bzero(r_srs, cell.nof_prb * 12 * sizeof(cf_t));
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!sf_symbols) {
return;
}
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
srslte_refsignal_ul_t refsignal;
if (srslte_refsignal_ul_init(&refsignal, cell)) {
mexErrMsgTxt("Error initiating UL refsignal\n");
return;
}
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
pusch_cfg.group_hopping_en = group_hopping_en;
pusch_cfg.sequence_hopping_en = false;
srslte_refsignal_ul_set_cfg(&refsignal, &pusch_cfg, NULL, &srs_cfg);
if (srslte_refsignal_srs_gen(&refsignal, sf_idx, r_srs)) {
mexErrMsgTxt("Error generating SRS\n");
return;
}
if (srslte_refsignal_srs_put(&refsignal, tti, r_srs, sf_symbols)) {
mexErrMsgTxt("Error allocating SRS\n");
return;
}
if (nlhs >= 1) {
uint32_t M_sc = srslte_refsignal_srs_M_sc(&refsignal); ;
mexutils_write_cf(r_srs, &plhs[0], M_sc, 1);
}
if (nlhs >= 2) {
mexutils_write_cf(sf_symbols, &plhs[1], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
}
srslte_refsignal_ul_free(&refsignal);
free(sf_symbols);
free(r_srs);
return;
}

@ -24,11 +24,12 @@
*
*/
#include "srslte/srslte.h"
#include <complex.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <complex.h>
#include "srslte/srslte.h"
@ -38,7 +39,9 @@ srslte_cell_t cell = {
1, // cell_id
SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_NORM,
SRSLTE_PHICH_R_1_6
SRSLTE_PHICH_R_1_6, // PHICH length
SRSLTE_FDD,
};
void usage(char *prog) {
@ -84,12 +87,12 @@ int main(int argc, char **argv) {
parse_args(argc,argv);
if (srslte_refsignal_ul_init(&refs, cell.nof_prb)) {
fprintf(stderr, "Error initializing UL reference signal\n");
ERROR("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");
ERROR("Error initializing UL reference signal\n");
goto do_exit;
}
@ -134,14 +137,17 @@ int main(int argc, char **argv) {
gettimeofday(&t[1], NULL);
pusch_cfg.group_hopping_en = group_hopping_en;
pusch_cfg.sequence_hopping_en = sequence_hopping_en;
srslte_refsignal_ul_set_cfg(&refs, &pusch_cfg, NULL, NULL);
srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, cshift_dmrs, signal);
srslte_refsignal_dmrs_pusch_gen(&refs, &pusch_cfg, nof_prb, sf_idx, cshift_dmrs, signal);
gettimeofday(&t[2], NULL);
get_time_interval(t);
printf("DMRS ExecTime: %ld us\n", t[0].tv_usec);
srslte_refsignal_srs_cfg_t srs_cfg;
ZERO_OBJECT(srs_cfg);
gettimeofday(&t[1], NULL);
srslte_refsignal_srs_gen(&refs, sf_idx, signal);
srslte_refsignal_srs_gen(&refs, &srs_cfg, &pusch_cfg, sf_idx, signal);
gettimeofday(&t[2], NULL);
get_time_interval(t);
printf("SRS ExecTime: %ld us\n", t[0].tv_usec);

@ -24,15 +24,14 @@
*
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/utils/debug.h"
#ifdef FORCE_STANDARD_RATE
static bool use_standard_rates = true;
@ -66,6 +65,7 @@ bool srslte_cell_isvalid(srslte_cell_t *cell) {
}
void srslte_cell_fprint(FILE *stream, srslte_cell_t *cell, uint32_t sfn) {
fprintf(stream, " - Type: %s\n", cell->frame_type == SRSLTE_FDD ? "FDD" : "TDD");
fprintf(stream, " - PCI: %d\n", cell->id);
fprintf(stream, " - Nof ports: %d\n", cell->nof_ports);
fprintf(stream, " - CP: %s\n", srslte_cp_string(cell->cp));
@ -92,15 +92,92 @@ void srslte_cell_fprint(FILE *stream, srslte_cell_t *cell, uint32_t sfn) {
}
bool srslte_sfidx_isvalid(uint32_t sf_idx) {
if (sf_idx <= SRSLTE_NSUBFRAMES_X_FRAME) {
// Internal type for srslte_tdd_sf_t
typedef enum { D = 0, U = 1, S = 2 } tdd_sf_t;
static srslte_tdd_sf_t tdd_sf[7][10] = {{D, S, U, U, U, D, S, U, U, U},
{D, S, U, U, D, D, S, U, U, D},
{D, S, U, D, D, D, S, U, D, D},
{D, S, U, U, U, D, D, D, D, D},
{D, S, U, U, D, D, D, D, D, D},
{D, S, U, D, D, D, D, D, D, D},
{D, S, U, U, U, D, S, U, U, D}};
static uint32_t tdd_nof_sf_symbols[10][3] = {
{3, 10, 1}, {9, 4, 1}, {10, 3, 1}, {11, 2, 1}, {12, 1, 1}, {3, 9, 2}, {9, 3, 2}, {10, 2, 2}, {11, 1, 1}, {6, 6, 2}};
srslte_tdd_sf_t srslte_sfidx_tdd_type(srslte_tdd_config_t tdd_config, uint32_t sf_idx)
{
if (tdd_config.sf_config < 7 && sf_idx < 10 && tdd_config.configured) {
return tdd_sf[tdd_config.sf_config][sf_idx];
} else {
return SRSLTE_TDD_SF_D;
}
}
uint32_t srslte_sfidx_tdd_nof_dw_slot(srslte_tdd_config_t tdd_config, uint32_t slot, srslte_cp_t cp)
{
uint32_t n = srslte_sfidx_tdd_nof_dw(tdd_config);
if (n < SRSLTE_CP_NSYMB(cp)) {
if (slot == 1) {
return 0;
} else {
return n;
}
} else {
if (slot == 1) {
return n - SRSLTE_CP_NSYMB(cp);
} else {
return SRSLTE_CP_NSYMB(cp);
}
}
}
uint32_t srslte_sfidx_tdd_nof_dw(srslte_tdd_config_t tdd_config)
{
if (tdd_config.ss_config < 10) {
return tdd_nof_sf_symbols[tdd_config.ss_config][0];
} else {
return 0;
}
}
uint32_t srslte_sfidx_tdd_nof_gp(srslte_tdd_config_t tdd_config)
{
if (tdd_config.ss_config < 10) {
return tdd_nof_sf_symbols[tdd_config.ss_config][1];
} else {
return 0;
}
}
const static uint32_t tdd_nof_harq[7] = {7, 4, 2, 3, 2, 1, 6};
uint32_t srslte_tdd_nof_harq(srslte_tdd_config_t tdd_config)
{
return tdd_nof_harq[tdd_config.sf_config];
}
uint32_t srslte_sfidx_tdd_nof_up(srslte_tdd_config_t tdd_config)
{
if (tdd_config.ss_config < 10) {
return tdd_nof_sf_symbols[tdd_config.ss_config][2];
} else {
return 0;
}
}
bool srslte_sfidx_isvalid(uint32_t sf_idx)
{
if (sf_idx <= SRSLTE_NOF_SF_X_FRAME) {
return true;
} else {
return false;
}
}
bool srslte_portid_isvalid(uint32_t port_id) {
bool srslte_portid_isvalid(uint32_t port_id)
{
if (port_id <= SRSLTE_MAX_PORTS) {
return true;
} else {
@ -210,7 +287,6 @@ uint32_t srslte_N_ta_new_rar(uint32_t ta) {
return ta*16;
}
void srslte_use_standard_symbol_size(bool enabled) {
use_standard_rates = enabled;
}
@ -430,7 +506,27 @@ struct lte_band lte_bands[SRSLTE_NOF_LTE_BANDS] = {
{30, 2350, 9770, 27660, 45, SRSLTE_BAND_GEO_AREA_NAR},
{31, 462.5, 9870, 27760, 10, SRSLTE_BAND_GEO_AREA_CALA},
{32, 1452, 9920, 0, 0, SRSLTE_BAND_GEO_AREA_EMEA},
{64, 0, 10359, 27809, 0, SRSLTE_BAND_GEO_AREA_ALL},
{33, 1900, 36000, 0, 0, SRSLTE_BAND_GEO_AREA_EMEA},
{34, 2010, 36200, 0, 0, SRSLTE_BAND_GEO_AREA_EMEA},
{35, 1850, 36350, 0, 0, SRSLTE_BAND_GEO_AREA_NAR},
{36, 1930, 36950, 0, 0, SRSLTE_BAND_GEO_AREA_NAR},
{37, 1910, 37550, 0, 0, SRSLTE_BAND_GEO_AREA_NAR},
{38, 2570, 37750, 0, 0, SRSLTE_BAND_GEO_AREA_EMEA},
{39, 1880, 38250, 0, 0, SRSLTE_BAND_GEO_AREA_APAC},
{40, 2300, 38650, 0, 0, SRSLTE_BAND_GEO_AREA_APAC},
{41, 2496, 39650, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{42, 3400, 41590, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{43, 3600, 43590, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{44, 703, 45590, 0, 0, SRSLTE_BAND_GEO_AREA_APAC},
{45, 1447, 46590, 0, 0, SRSLTE_BAND_GEO_AREA_APAC},
{46, 5150, 46790, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{47, 5855, 54540, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{48, 3550, 55240, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{49, 3550, 56740, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{50, 1432, 58240, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{51, 1427, 59090, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{52, 3300, 59140, 0, 0, SRSLTE_BAND_GEO_AREA_ALL},
{64, 0, 60139, 27809, 0, SRSLTE_BAND_GEO_AREA_ALL},
{65, 2110, 65536, 131072, 90, SRSLTE_BAND_GEO_AREA_ALL},
{66, 2110, 66436, 131972, 90, SRSLTE_BAND_GEO_AREA_NAR},
{67, 738, 67336, 0, 0, SRSLTE_BAND_GEO_AREA_EMEA},
@ -440,43 +536,43 @@ struct lte_band lte_bands[SRSLTE_NOF_LTE_BANDS] = {
{71, 0, 68586, 133122, 0, SRSLTE_BAND_GEO_AREA_NAR} // dummy band to bound band 70 earfcn
};
int srslte_str2mimotype(char *mimo_type_str, srslte_mimo_type_t *type) {
int srslte_str2mimotype(char* mimo_type_str, srslte_tx_scheme_t* type)
{
int i = 0;
/* Low case */
while (mimo_type_str[i] |= ' ', mimo_type_str[++i]);
if (!strcmp(mimo_type_str, "single") || !strcmp(mimo_type_str, "port0")) {
*type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
} else if (!strcmp(mimo_type_str, "diversity") || !strcmp(mimo_type_str, "txdiversity")) {
*type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else if (!strcmp(mimo_type_str, "multiplex") || !strcmp(mimo_type_str, "spatialmux")) {
*type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
} else if (!strcmp(mimo_type_str, "cdd")) {
*type = SRSLTE_MIMO_TYPE_CDD;
} else {
return SRSLTE_ERROR;
}
srslte_tx_scheme_t t = SRSLTE_TXSCHEME_PORT0;
do {
if (!strcmp(mimo_type_str, srslte_mimotype2str(t))) {
*type = t;
return SRSLTE_SUCCESS;
}
t++;
} while (t <= SRSLTE_TXSCHEME_CDD);
return SRSLTE_ERROR;
}
char *srslte_mimotype2str(srslte_mimo_type_t mimo_type) {
char* srslte_mimotype2str(srslte_tx_scheme_t mimo_type)
{
switch (mimo_type) {
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
return "Single";
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
return "Diversity";
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
return "Multiplex";
case SRSLTE_MIMO_TYPE_CDD:
return "CDD";
case SRSLTE_TXSCHEME_PORT0:
return "p0";
case SRSLTE_TXSCHEME_DIVERSITY:
return "div";
case SRSLTE_TXSCHEME_SPATIALMUX:
return "mux";
case SRSLTE_TXSCHEME_CDD:
return "cdd";
default:
return "N/A";
}
}
float get_fd(struct lte_band *band, uint32_t dl_earfcn) {
float get_fd(struct lte_band* band, uint32_t dl_earfcn)
{
if (dl_earfcn >= band->dl_earfcn_offset) {
return band->fd_low_mhz + 0.1 * (dl_earfcn - band->dl_earfcn_offset);
} else {
@ -492,10 +588,24 @@ float get_fu(struct lte_band *band, uint32_t ul_earfcn) {
}
}
int srslte_band_get_band(uint32_t dl_earfcn) {
bool srslte_band_is_tdd(uint32_t band)
{
uint32_t i = 0;
while (i < SRSLTE_NOF_LTE_BANDS && lte_bands[i].band != band) {
i++;
}
if (i == SRSLTE_NOF_LTE_BANDS) {
ERROR("Invalid Band %d\n", band);
return false;
}
return lte_bands[i].ul_earfcn_offset == 0;
}
int srslte_band_get_band(uint32_t dl_earfcn)
{
uint32_t i = SRSLTE_NOF_LTE_BANDS - 1;
if (dl_earfcn > lte_bands[i].dl_earfcn_offset) {
fprintf(stderr, "Invalid DL_EARFCN=%d\n", dl_earfcn);
ERROR("Invalid DL_EARFCN=%d\n", dl_earfcn);
}
i--;
while (i > 0 && lte_bands[i].dl_earfcn_offset > dl_earfcn) {
@ -504,10 +614,11 @@ int srslte_band_get_band(uint32_t dl_earfcn) {
return lte_bands[i].band;
}
float srslte_band_fd(uint32_t dl_earfcn) {
float srslte_band_fd(uint32_t dl_earfcn)
{
uint32_t i = SRSLTE_NOF_LTE_BANDS-1;
if (dl_earfcn > lte_bands[i].dl_earfcn_offset) {
fprintf(stderr, "Invalid DL_EARFCN=%d\n", dl_earfcn);
ERROR("Invalid DL_EARFCN=%d\n", dl_earfcn);
}
i--;
while(i > 0 && lte_bands[i].dl_earfcn_offset>dl_earfcn) {
@ -520,7 +631,7 @@ float srslte_band_fd(uint32_t dl_earfcn) {
float srslte_band_fu(uint32_t ul_earfcn) {
uint32_t i = SRSLTE_NOF_LTE_BANDS-1;
if (ul_earfcn > lte_bands[i].ul_earfcn_offset) {
fprintf(stderr, "Invalid UL_EARFCN=%d\n", ul_earfcn);
ERROR("Invalid UL_EARFCN=%d\n", ul_earfcn);
}
i--;
while(i > 0 && (lte_bands[i].ul_earfcn_offset>ul_earfcn || lte_bands[i].ul_earfcn_offset == 0)) {
@ -532,7 +643,7 @@ float srslte_band_fu(uint32_t ul_earfcn) {
uint32_t srslte_band_ul_earfcn(uint32_t dl_earfcn) {
uint32_t i = SRSLTE_NOF_LTE_BANDS-1;
if (dl_earfcn > lte_bands[i].dl_earfcn_offset) {
fprintf(stderr, "Invalid DL_EARFCN=%d\n", dl_earfcn);
ERROR("Invalid DL_EARFCN=%d\n", dl_earfcn);
}
i--;
while(i > 0 && lte_bands[i].dl_earfcn_offset>dl_earfcn) {
@ -545,7 +656,9 @@ int srslte_band_get_fd_band_all(uint32_t band, srslte_earfcn_t *earfcn, uint32_t
return srslte_band_get_fd_band(band, earfcn, -1, -1, max_elems);
}
int srslte_band_get_fd_band(uint32_t band, srslte_earfcn_t *earfcn, int start_earfcn, int end_earfcn, uint32_t max_elems) {
int srslte_band_get_fd_band(
uint32_t band, srslte_earfcn_t* earfcn, int start_earfcn, int end_earfcn, uint32_t max_elems)
{
uint32_t i, j;
uint32_t nof_earfcn;
i=0;
@ -553,14 +666,14 @@ int srslte_band_get_fd_band(uint32_t band, srslte_earfcn_t *earfcn, int start_ea
i++;
}
if (i >= SRSLTE_NOF_LTE_BANDS - 1) {
fprintf(stderr, "Error: Invalid band %d\n", band);
ERROR("Error: Invalid band %d\n", band);
return SRSLTE_ERROR;
}
if (end_earfcn == -1) {
end_earfcn = lte_bands[i+1].dl_earfcn_offset-1;
} else {
if (end_earfcn > lte_bands[i+1].dl_earfcn_offset-1) {
fprintf(stderr, "Error: Invalid end earfcn %d. Max is %d\n", end_earfcn, lte_bands[i+1].dl_earfcn_offset-1);
ERROR("Error: Invalid end earfcn %d. Max is %d\n", end_earfcn, lte_bands[i + 1].dl_earfcn_offset - 1);
return SRSLTE_ERROR;
}
}
@ -568,7 +681,7 @@ int srslte_band_get_fd_band(uint32_t band, srslte_earfcn_t *earfcn, int start_ea
start_earfcn = lte_bands[i].dl_earfcn_offset;
} else {
if (start_earfcn < lte_bands[i].dl_earfcn_offset) {
fprintf(stderr, "Error: Invalid start earfcn %d. Min is %d\n", start_earfcn, lte_bands[i].dl_earfcn_offset);
ERROR("Error: Invalid start earfcn %d. Min is %d\n", start_earfcn, lte_bands[i].dl_earfcn_offset);
return SRSLTE_ERROR;
}
}
@ -612,4 +725,16 @@ uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2) {
}
}
uint32_t srslte_print_check(char* s, size_t max_len, uint32_t cur_len, const char* format, ...)
{
if (cur_len < max_len - 1) {
va_list args;
va_start(args, format);
cur_len += vsnprintf(&s[cur_len], max_len - cur_len, format, args);
va_end(args);
} else {
ERROR("Buffer full when printing string\n");
exit(-1);
}
return cur_len;
}

@ -28,11 +28,11 @@
#include <stdio.h>
#include <strings.h>
#include <pthread.h>
#include <srslte/phy/common/sequence.h>
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/utils/vector.h"
#include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#define Nc 1600
@ -54,14 +54,12 @@ 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);
ERROR("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);
ERROR("Error generating pseudo-random sequence: len %d is greater than allocated len %d\n", len, q->max_len);
return -1;
}
pthread_mutex_lock(&mutex);
@ -90,8 +88,7 @@ int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed
uint32_t *x1, *x2;
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);
ERROR("Error generating pseudo-random sequence: len %d is greater than allocated len %d\n", len, q->max_len);
return -1;
}

@ -24,12 +24,11 @@
*
*/
#include <math.h>
#include "srslte/srslte.h"
#include <complex.h>
#include <fftw3.h>
#include <math.h>
#include <string.h>
#include <srslte/srslte.h>
#include "srslte/phy/dft/dft.h"
#include "srslte/phy/utils/vector.h"
@ -81,8 +80,10 @@ int srslte_dft_replan(srslte_dft_plan_t *plan, const int new_dft_points) {
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);
ERROR("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;
}
}
@ -312,7 +313,7 @@ void srslte_dft_run_guru_c(srslte_dft_plan_t *plan) {
if (plan->is_guru == true) {
fftwf_execute(plan->p);
} else {
fprintf(stderr, "srslte_dft_run_guru_c: the selected plan is not guru!\n");
ERROR("srslte_dft_run_guru_c: the selected plan is not guru!\n");
}
}

@ -52,7 +52,7 @@ int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb, bool
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, is_tx?SRSLTE_DFT_FORWARD:SRSLTE_DFT_BACKWARD)) {
fprintf(stderr, "Error: Creating DFT plan %d\n",i);
ERROR("Error: Creating DFT plan %d\n", i);
goto clean_exit;
}
srslte_dft_plan_set_norm(&q->dft_plan[i], true);
@ -106,7 +106,7 @@ int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
{
if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) {
fprintf(stderr, "Error invalid number of PRB (%d)\n", nof_prb);
ERROR("Error invalid number of PRB (%d)\n", nof_prb);
return SRSLTE_ERROR;
}

@ -24,12 +24,12 @@
*
*/
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "srslte/srslte.h"
#include <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/dft/dft.h"
@ -60,7 +60,7 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, c
q->out_buffer= out_buffer;
if (srslte_dft_plan_c(&q->fft_plan, symbol_sz, dir)) {
fprintf(stderr, "Error: Creating DFT plan\n");
ERROR("Error: Creating DFT plan\n");
return -1;
}
@ -96,7 +96,7 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, c
in_buffer + cp1 + q->slot_sz * slot,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
ERROR("Error: Creating DFT plan (1)\n");
return -1;
}
} else {
@ -104,7 +104,7 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, c
q->tmp + q->nof_symbols * q->symbol_sz * slot,
out_buffer + cp1 + q->slot_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
ERROR("Error: Creating DFT plan (1)\n");
return -1;
}
}
@ -143,7 +143,7 @@ void srslte_ofdm_set_non_mbsfn_region(srslte_ofdm_t *q, uint8_t 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");
ERROR("Error: Creating DFT plan\n");
return -1;
}
@ -190,7 +190,7 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof
in_buffer + cp1 + q->slot_sz * slot,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
ERROR("Error: Creating DFT plan (1)\n");
return -1;
}
} else {
@ -198,7 +198,7 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof
q->tmp + q->nof_symbols * q->symbol_sz * slot,
out_buffer + cp1 + q->slot_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
ERROR("Error: Creating DFT plan (1)\n");
return -1;
}
}
@ -240,7 +240,7 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) {
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, 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);
ERROR("Error: Invalid nof_prb=%d\n", max_prb);
return -1;
}
q->max_prb = max_prb;
@ -251,7 +251,7 @@ int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer,
{
int symbol_sz = srslte_symbol_sz(max_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
ERROR("Error: Invalid nof_prb=%d\n", max_prb);
return -1;
}
q->max_prb = max_prb;
@ -265,7 +265,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t
int symbol_sz = srslte_symbol_sz(max_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
ERROR("Error: Invalid nof_prb=%d\n", max_prb);
return -1;
}
q->max_prb = max_prb;
@ -291,7 +291,7 @@ int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer,
int symbol_sz = srslte_symbol_sz(nof_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
ERROR("Error: Invalid nof_prb=%d\n", nof_prb);
return -1;
}
q->max_prb = nof_prb;
@ -313,13 +313,14 @@ 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);
ERROR("Error: Invalid nof_prb=%d\n", nof_prb);
return -1;
}
return srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb);
} else {
fprintf(stderr, "OFDM (Rx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n",
nof_prb, q->max_prb);
ERROR("OFDM (Rx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n",
nof_prb,
q->max_prb);
return -1;
}
}
@ -331,7 +332,7 @@ int srslte_ofdm_tx_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);
ERROR("Error: Invalid nof_prb=%d\n", nof_prb);
return -1;
}
@ -346,8 +347,9 @@ int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
}
return ret;
} else {
fprintf(stderr, "OFDM (Tx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n",
nof_prb, q->max_prb);
ERROR("OFDM (Tx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n",
nof_prb,
q->max_prb);
return -1;
}
}
@ -550,7 +552,7 @@ void srslte_ofdm_tx_slot(srslte_ofdm_t *q, int slot_in_sf) {
for (int i = 0; i < q->slot_sz; i++) {
float error = cabsf(output1[i] - output2[i])/cabsf(output2[i]);
cf_t k = output1[i]/output2[i];
if (error > 0.1) printf("%d/%05d error=%f output=%+f%+fi gold=%+f%+fi k=%+f%+fi\n", slot_in_sf, i, error,
if (error > 0.1) printf("%d/%05d error=%f output=%+f%+fi gold=%+f%+fi k=%+f%+fi\n", slot_in_sf, i, ERROR(
__real__ output1[i], __imag__ output1[i],
__real__ output2[i], __imag__ output2[i],
__real__ k, __imag__ k);

@ -115,13 +115,13 @@ int main(int argc, char **argv) {
bzero(outifft, sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2);
if (srslte_ofdm_rx_init(&fft, cp, outifft, outfft, n_prb)) {
fprintf(stderr, "Error initializing FFT\n");
ERROR("Error initializing FFT\n");
exit(-1);
}
srslte_ofdm_set_normalize(&fft, true);
if (srslte_ofdm_tx_init(&ifft, cp, input, outifft, n_prb)) {
fprintf(stderr, "Error initializing iFFT\n");
ERROR("Error initializing iFFT\n");
exit(-1);
}
srslte_ofdm_set_normalize(&ifft, true);

@ -26,18 +26,16 @@
#include "srslte/phy/enb/enb_dl.h"
#include "srslte/srslte.h"
#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)
#define CURRENT_SFLEN SRSLTE_SF_LEN(CURRENT_FFTSIZE)
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_NOF_RE(q->cell)
#define SRSLTE_ENB_RF_AMP 0.1
@ -51,74 +49,68 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], u
bzero(q, sizeof(srslte_enb_dl_t));
q->cfi = 3;
q->tx_amp = SRSLTE_ENB_RF_AMP;
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][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)];
}
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (srslte_ofdm_tx_init(&q->ifft[i], SRSLTE_CP_NORM, q->sf_symbols[i], out_buffer[i], max_prb)) {
fprintf(stderr, "Error initiating FFT (%d)\n", i);
ERROR("Error initiating FFT (%d)\n", i);
goto clean_exit;
}
}
if (srslte_ofdm_tx_init_mbsfn(&q->ifft_mbsfn, SRSLTE_CP_EXT, q->sf_symbols[0], out_buffer[0], max_prb)) {
fprintf(stderr, "Error initiating FFT \n");
ERROR("Error initiating FFT \n");
goto clean_exit;
}
if (srslte_pbch_init(&q->pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
ERROR("Error creating PBCH object\n");
goto clean_exit;
}
if (srslte_pcfich_init(&q->pcfich, 0)) {
fprintf(stderr, "Error creating PCFICH object\n");
ERROR("Error creating PCFICH object\n");
goto clean_exit;
}
if (srslte_phich_init(&q->phich, 0)) {
fprintf(stderr, "Error creating PHICH object\n");
ERROR("Error creating PHICH object\n");
goto clean_exit;
}
int mbsfn_area_id = 1;
if (srslte_pmch_init(&q->pmch, max_prb)) {
fprintf(stderr, "Error creating PMCH object\n");
if (srslte_pmch_init(&q->pmch, max_prb, 1)) {
ERROR("Error creating PMCH object\n");
}
srslte_pmch_set_area_id(&q->pmch, mbsfn_area_id);
if (srslte_pdcch_init_enb(&q->pdcch, max_prb)) {
fprintf(stderr, "Error creating PDCCH object\n");
ERROR("Error creating PDCCH object\n");
goto clean_exit;
}
if (srslte_pdsch_init_enb(&q->pdsch, max_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
ERROR("Error creating PDSCH object\n");
goto clean_exit;
}
if (srslte_refsignal_cs_init(&q->csr_signal, max_prb)) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
ERROR("Error initializing CSR signal (%d)\n", ret);
goto clean_exit;
}
if (srslte_refsignal_mbsfn_init(&q->mbsfnr_signal, max_prb)) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
ERROR("Error initializing CSR signal (%d)\n", ret);
goto clean_exit;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid parameters\n");
ERROR("Invalid parameters\n");
}
clean_exit:
@ -160,70 +152,64 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell)
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
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));
q->cell = cell;
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error resizing REGs\n");
ERROR("Error resizing REGs\n");
return SRSLTE_ERROR;
}
for (int i = 0; i < q->cell.nof_ports; i++) {
q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, SRSLTE_CP_NORM)];
if (srslte_ofdm_tx_set_prb(&q->ifft[i], q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error re-planning iFFT (%d)\n", i);
ERROR("Error re-planning iFFT (%d)\n", i);
return SRSLTE_ERROR;
}
}
if (srslte_ofdm_tx_set_prb(&q->ifft_mbsfn, SRSLTE_CP_EXT, q->cell.nof_prb)) {
fprintf(stderr, "Error re-planning ifft_mbsfn\n");
ERROR("Error re-planning ifft_mbsfn\n");
return SRSLTE_ERROR;
}
srslte_ofdm_set_non_mbsfn_region(&q->ifft_mbsfn, 2);
//srslte_ofdm_set_normalize(&q->ifft_mbsfn, true);
if (srslte_pbch_set_cell(&q->pbch, q->cell)) {
fprintf(stderr, "Error creating PBCH object\n");
ERROR("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");
ERROR("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");
ERROR("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");
ERROR("Error creating PDCCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
ERROR("Error creating PDSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pmch_set_cell(&q->pmch, q->cell)) {
fprintf(stderr, "Error creating PMCH object\n");
ERROR("Error creating PMCH 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);
ERROR("Error initializing CSR signal (%d)\n", ret);
return SRSLTE_ERROR;
}
int mbsfn_area_id = 1;
if (srslte_refsignal_mbsfn_set_cell(&q->mbsfnr_signal, q->cell, mbsfn_area_id)) {
fprintf(stderr, "Error initializing MBSFNR signal (%d)\n",ret);
ERROR("Error initializing MBSFNR signal (%d)\n", ret);
return SRSLTE_ERROR;
}
/* Generate PSS/SSS signals */
@ -233,37 +219,22 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_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);
ERROR("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_non_mbsfn_region(srslte_enb_dl_t *q, uint8_t non_mbsfn_region)
{
srslte_ofdm_set_non_mbsfn_region(&q->ifft_mbsfn, non_mbsfn_region);
}
void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp)
{
q->tx_amp = amp;
}
void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, uint32_t cfi)
int srslte_enb_dl_add_rnti(srslte_enb_dl_t* q, uint16_t rnti)
{
q->cfi = cfi;
return srslte_pdsch_set_rnti(&q->pdsch, rnti);
}
void srslte_enb_dl_set_power_allocation(srslte_enb_dl_t *q, float rho_a, float rho_b)
void srslte_enb_dl_rem_rnti(srslte_enb_dl_t* q, uint16_t rnti)
{
if (q) {
q->rho_b = rho_b;
srslte_pdsch_set_power_allocation(&q->pdsch, rho_a);
}
srslte_pdsch_free_rnti(&q->pdsch, rnti);
}
#ifdef resolve
void srslte_enb_dl_apply_power_allocation(srslte_enb_dl_t *q)
{
uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp);
@ -320,15 +291,19 @@ void srslte_enb_dl_prepare_power_allocation(srslte_enb_dl_t *q)
}
}
void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q)
#endif
static void clear_sf(srslte_enb_dl_t* q)
{
for (int i = 0; i < q->cell.nof_ports; i++) {
bzero(q->sf_symbols[i], CURRENT_SFLEN_RE * sizeof(cf_t));
}
}
void srslte_enb_dl_put_sync(srslte_enb_dl_t *q, uint32_t sf_idx)
static void put_sync(srslte_enb_dl_t* q)
{
uint32_t sf_idx = q->dl_sf.tti % 10;
if (sf_idx == 0 || sf_idx == 5) {
for (int p = 0; p < q->cell.nof_ports; p++) {
srslte_pss_put_slot(q->pss_signal, q->sf_symbols[p], q->cell.nof_prb, q->cell.cp);
@ -338,196 +313,163 @@ void srslte_enb_dl_put_sync(srslte_enb_dl_t *q, uint32_t sf_idx)
}
}
void srslte_enb_dl_put_refs(srslte_enb_dl_t *q, uint32_t sf_idx)
static void put_refs(srslte_enb_dl_t* q)
{
uint32_t sf_idx = q->dl_sf.tti % 10;
if (q->dl_sf.sf_type == SRSLTE_SF_MBSFN) {
srslte_refsignal_mbsfn_put_sf(
q->cell, 0, q->csr_signal.pilots[0][sf_idx], q->mbsfnr_signal.pilots[0][sf_idx], q->sf_symbols[0]);
} else {
for (int p = 0; p < q->cell.nof_ports; p++) {
srslte_refsignal_cs_put_sf(q->cell, (uint32_t) p, q->csr_signal.pilots[p / 2][sf_idx], q->sf_symbols[p]);
srslte_refsignal_cs_put_sf(&q->csr_signal, &q->dl_sf, (uint32_t)p, q->sf_symbols[p]);
}
}
void srslte_enb_dl_put_mib(srslte_enb_dl_t *q, uint32_t tti)
{
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
if ((tti%10) == 0) {
srslte_pbch_mib_pack(&q->cell, tti/10, bch_payload);
srslte_pbch_encode(&q->pbch, bch_payload, q->slot1_symbols, ((tti/10)%4));
}
}
void srslte_enb_dl_put_pcfich(srslte_enb_dl_t *q, uint32_t sf_idx)
static void put_mib(srslte_enb_dl_t* q)
{
srslte_pcfich_encode(&q->pcfich, q->cfi, q->sf_symbols, sf_idx);
}
void srslte_enb_dl_put_phich(srslte_enb_dl_t *q, uint8_t ack, uint32_t n_prb_lowest,
uint32_t n_dmrs, uint32_t sf_idx)
{
uint32_t ngroup, nseq;
srslte_phich_calc(&q->phich, n_prb_lowest, n_dmrs, &ngroup, &nseq);
srslte_phich_encode(&q->phich, ack, ngroup, nseq, sf_idx, q->sf_symbols);
}
void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti)
{
uint32_t sf_idx = tti%10;
srslte_enb_dl_put_sync(q, sf_idx);
srslte_enb_dl_put_refs(q, sf_idx);
srslte_enb_dl_put_mib(q, tti);
srslte_enb_dl_put_pcfich(q, sf_idx);
}
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
void srslte_enb_dl_put_mbsfn_base(srslte_enb_dl_t *q, uint32_t tti)
{
uint32_t sf_idx1 = tti%10;
srslte_enb_dl_put_pcfich(q, sf_idx1);
srslte_refsignal_mbsfn_put_sf(q->cell, 0,q->csr_signal.pilots[0][sf_idx1], q->mbsfnr_signal.pilots[0][sf_idx1], q->sf_symbols[0]);
}
uint32_t sf_idx = q->dl_sf.tti % 10;
uint32_t sfn = q->dl_sf.tti / 10;
void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q)
{
// TODO: PAPR control
float norm_factor = 0.05f / sqrt(q->cell.nof_prb);
for (int i = 0; i < q->cell.nof_ports; i++) {
srslte_ofdm_tx_sf(&q->ifft[i]);
srslte_vec_sc_prod_cfc(q->ifft[i].out_buffer, norm_factor, q->ifft[i].out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
if (sf_idx == 0) {
srslte_pbch_mib_pack(&q->cell, sfn, bch_payload);
srslte_pbch_encode(&q->pbch, bch_payload, q->sf_symbols, sfn % 4);
}
}
void srslte_enb_dl_gen_signal_mbsfn(srslte_enb_dl_t *q)
static void put_pcfich(srslte_enb_dl_t* q)
{
float norm_factor = 0.05f / sqrt(q->cell.nof_prb);
srslte_ofdm_tx_sf(&q->ifft_mbsfn);
srslte_vec_sc_prod_cfc(q->ifft_mbsfn.out_buffer, norm_factor, q->ifft_mbsfn.out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
srslte_pcfich_encode(&q->pcfich, &q->dl_sf, q->sf_symbols);
}
int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti)
void srslte_enb_dl_put_base(srslte_enb_dl_t* q, srslte_dl_sf_cfg_t* dl_sf)
{
return srslte_pdsch_set_rnti(&q->pdsch, rnti);
srslte_ofdm_set_non_mbsfn_region(&q->ifft_mbsfn, dl_sf->non_mbsfn_region);
q->dl_sf = *dl_sf;
clear_sf(q);
put_sync(q);
put_refs(q);
put_mib(q);
put_pcfich(q);
}
void srslte_enb_dl_rem_rnti(srslte_enb_dl_t *q, uint16_t rnti)
void srslte_enb_dl_put_phich(srslte_enb_dl_t* q, srslte_phich_grant_t* grant, bool ack)
{
srslte_pdsch_free_rnti(&q->pdsch, rnti);
srslte_phich_resource_t resource;
srslte_phich_calc(&q->phich, grant, &resource);
srslte_phich_encode(&q->phich, &q->dl_sf, resource, ack, q->sf_symbols);
}
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)
int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t* q, srslte_dci_cfg_t* dci_cfg, srslte_dci_dl_t* dci_dl)
{
srslte_dci_msg_t dci_msg;
bzero(&dci_msg, sizeof(dci_msg));
bool rnti_is_user = true;
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || (rnti >= SRSLTE_RARNTI_START && rnti <= SRSLTE_RARNTI_END)) {
rnti_is_user = false;
}
ZERO_OBJECT(dci_msg);
if (srslte_dci_msg_pack_pdsch(grant, format, &dci_msg, q->cell.nof_prb, q->cell.nof_ports, rnti_is_user)) {
fprintf(stderr, "Error packing DCI grant\n");
if (srslte_dci_msg_pack_pdsch(&q->cell, &q->dl_sf, dci_cfg, dci_dl, &dci_msg)) {
ERROR("Error packing DL DCI\n");
}
if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) {
fprintf(stderr, "Error encoding DCI message\n");
if (srslte_pdcch_encode(&q->pdcch, &q->dl_sf, &dci_msg, q->sf_symbols)) {
ERROR("Error encoding DL DCI message\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant,
srslte_dci_location_t location,
uint16_t rnti, uint32_t sf_idx)
int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t* q, srslte_dci_cfg_t* dci_cfg, srslte_dci_ul_t* dci_ul)
{
srslte_dci_msg_t dci_msg;
bzero(&dci_msg, sizeof(dci_msg));
ZERO_OBJECT(dci_msg);
srslte_dci_msg_pack_pusch(grant, &dci_msg, q->cell.nof_prb);
if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) {
fprintf(stderr, "Error encoding DCI message\n");
if (srslte_dci_msg_pack_pusch(&q->cell, &q->dl_sf, dci_cfg, dci_ul, &dci_msg)) {
ERROR("Error packing UL DCI\n");
}
if (srslte_pdcch_encode(&q->pdcch, &q->dl_sf, &dci_msg, q->sf_symbols)) {
ERROR("Error encoding UL DCI message\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
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, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type)
int srslte_enb_dl_put_pdsch(srslte_enb_dl_t* q, srslte_pdsch_cfg_t* pdsch, uint8_t* data[SRSLTE_MAX_CODEWORDS])
{
uint32_t pmi = 0;
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
/* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */
if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
switch(nof_tb) {
case 1:
if (grant->pinfo == 0) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else if (grant->pinfo > 0 && grant->pinfo < 5) {
pmi = grant->pinfo - 1;
} else {
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR;
}
break;
case 2:
if (grant->pinfo < 2) {
pmi = grant->pinfo;
} else {
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR;
}
break;
default:
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR;
}
return srslte_pdsch_encode(&q->pdsch, &q->dl_sf, pdsch, data, q->sf_symbols);
}
/* Configure pdsch_cfg parameters */
if (srslte_pdsch_cfg_mimo(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx, mimo_type, pmi)) {
ERROR("Error configuring PDSCH (rnti=0x%04x)", rnti);
return SRSLTE_ERROR;
int srslte_enb_dl_put_pmch(srslte_enb_dl_t* q, srslte_pmch_cfg_t* pmch_cfg, uint8_t* data)
{
return srslte_pmch_encode(&q->pmch, &q->dl_sf, pmch_cfg, data, q->sf_symbols);
}
/* Encode PDSCH */
if (srslte_pdsch_encode(&q->pdsch, &q->pdsch_cfg, softbuffer, data, rnti, q->sf_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
return SRSLTE_ERROR;
void srslte_enb_dl_gen_signal(srslte_enb_dl_t* q)
{
// TODO: PAPR control
float norm_factor = 0.05f / sqrt(q->cell.nof_prb);
if (q->dl_sf.sf_type == SRSLTE_SF_MBSFN) {
srslte_ofdm_tx_sf(&q->ifft_mbsfn);
srslte_vec_sc_prod_cfc(
q->ifft_mbsfn.out_buffer, norm_factor, q->ifft_mbsfn.out_buffer, (uint32_t)SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
} else {
for (int i = 0; i < q->cell.nof_ports; i++) {
srslte_ofdm_tx_sf(&q->ifft[i]);
srslte_vec_sc_prod_cfc(
q->ifft[i].out_buffer, norm_factor, q->ifft[i].out_buffer, (uint32_t)SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
}
}
return SRSLTE_SUCCESS;
}
int srslte_enb_dl_put_pmch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer, uint32_t sf_idx, uint8_t *data_mbms)
bool srslte_enb_dl_gen_cqi_periodic(
srslte_cell_t* cell, srslte_dl_cfg_t* dl_cfg, uint32_t tti, uint32_t ri, srslte_cqi_cfg_t* cqi_cfg)
{
bool cqi_enabled = false;
if (srslte_cqi_periodic_ri_send(&dl_cfg->cqi_report, tti, cell->frame_type)) {
cqi_cfg->ri_len = 1; /* Asumes only 1 bit for RI */
cqi_enabled = true;
} else if (srslte_cqi_periodic_send(&dl_cfg->cqi_report, tti, cell->frame_type)) {
cqi_cfg->type = SRSLTE_CQI_TYPE_WIDEBAND;
if (dl_cfg->tm == SRSLTE_TM4) {
cqi_cfg->pmi_present = true;
cqi_cfg->rank_is_not_one = ri > 0;
}
cqi_enabled = true;
cqi_cfg->data_enable = cqi_enabled;
}
return cqi_enabled;
}
bool srslte_enb_dl_gen_cqi_aperiodic(srslte_cell_t* cell,
srslte_dl_cfg_t* dl_cfg,
uint32_t ri,
srslte_cqi_cfg_t* cqi_cfg)
{
/* Encode PMCH */
bool cqi_enabled = false;
srslte_cqi_report_cfg_t* cqi_report_cfg = &dl_cfg->cqi_report;
int mbsfn_area_id = 1;
if (srslte_pmch_cfg(&q->pmch_cfg, q->cell, grant, q->cfi, sf_idx)) {
fprintf(stderr, "Error configuring PMCH\n");
return SRSLTE_ERROR;
}
/* Encode PMCH */
if (srslte_pmch_encode(&q->pmch, &q->pmch_cfg, softbuffer, data_mbms, mbsfn_area_id, q->sf_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
return SRSLTE_ERROR;
cqi_cfg->type = SRSLTE_CQI_TYPE_SUBBAND_HL;
if (dl_cfg->tm == SRSLTE_TM3 || dl_cfg->tm == SRSLTE_TM4) {
cqi_cfg->ri_present = true;
}
cqi_cfg->N = (cell->nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell->nof_prb) : 0;
cqi_cfg->four_antenna_ports = (cell->nof_ports == 4);
cqi_cfg->pmi_present = (cqi_report_cfg->pmi_idx != 0);
cqi_cfg->rank_is_not_one = ri > 0;
cqi_cfg->data_enable = true;
return SRSLTE_SUCCESS;
return cqi_enabled;
}
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)
void srslte_enb_dl_save_signal(srslte_enb_dl_t* q)
{
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));
uint32_t tti = q->dl_sf.tti;
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));
snprintf(tmpstr, 64, "sf_symbols_%d", tti);
srslte_vec_save_file(tmpstr, q->sf_symbols[0], SRSLTE_NOF_RE(q->cell) * sizeof(cf_t));
/*
int cb_len = q->pdsch_cfg.cb_segm[0].K1;
@ -537,11 +479,6 @@ void srslte_enb_dl_save_signal(srslte_enb_dl_t *q, srslte_softbuffer_tx_t *softb
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);
// q->dci.mcs[0].idx, q->dci.mcs[0].tbs, rv_idx, rnti);
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save