mirror of https://github.com/PentHertz/srsLTE.git
Merge to next_with_matlab
This commit is contained in:
parent
fa741f24e7
commit
6142a5f9e5
|
@ -118,7 +118,7 @@ int parse_args(prog_args_t *args, int argc, char **argv) {
|
|||
/**********************************************************************/
|
||||
|
||||
/* TODO: Do something with the output data */
|
||||
uint8_t data[1000000];
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS];
|
||||
|
||||
bool go_exit = false;
|
||||
void sig_int_handler(int signo)
|
||||
|
@ -183,6 +183,9 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -322,7 +325,7 @@ int main(int argc, char **argv) {
|
|||
nof_trials++;
|
||||
} else {
|
||||
printf("Decoded SIB1. Payload: ");
|
||||
srslte_vec_fprint_byte(stdout, data, n/8);;
|
||||
srslte_vec_fprint_byte(stdout, data[0], n/8);;
|
||||
state = MEASURE;
|
||||
}
|
||||
}
|
||||
|
@ -386,6 +389,12 @@ int main(int argc, char **argv) {
|
|||
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");
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
#include <srslte/phy/phch/pdsch_cfg.h>
|
||||
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
|
@ -55,19 +55,21 @@ char *output_file_name = NULL;
|
|||
#define DOWN_KEY 66
|
||||
|
||||
srslte_cell_t cell = {
|
||||
25, // nof_prb
|
||||
1, // nof_ports
|
||||
0, // cell_id
|
||||
SRSLTE_CP_NORM, // cyclic prefix
|
||||
SRSLTE_PHICH_R_1, // PHICH resources
|
||||
SRSLTE_PHICH_NORM // PHICH length
|
||||
25, // nof_prb
|
||||
1, // nof_ports
|
||||
0, // cell_id
|
||||
SRSLTE_CP_NORM, // cyclic prefix
|
||||
SRSLTE_PHICH_NORM, // PHICH length
|
||||
SRSLTE_PHICH_R_1 // PHICH resources
|
||||
};
|
||||
|
||||
|
||||
int net_port = -1; // -1 generates random dataThat means there is some problem sending samples to the device
|
||||
|
||||
uint32_t cfi=3;
|
||||
uint32_t mcs_idx = 1, last_mcs_idx = 1;
|
||||
int nof_frames = -1;
|
||||
char mimo_type_str[32] = "single";
|
||||
uint32_t nof_tb = 1;
|
||||
|
||||
char *rf_args = "";
|
||||
float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
|
||||
|
@ -80,14 +82,14 @@ srslte_pcfich_t pcfich;
|
|||
srslte_pdcch_t pdcch;
|
||||
srslte_pdsch_t pdsch;
|
||||
srslte_pdsch_cfg_t pdsch_cfg;
|
||||
srslte_softbuffer_tx_t softbuffer;
|
||||
srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS];
|
||||
srslte_regs_t regs;
|
||||
srslte_ra_dl_dci_t ra_dl;
|
||||
|
||||
cf_t *sf_buffer = NULL, *output_buffer = NULL;
|
||||
cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL}, *output_buffer [SRSLTE_MAX_PORTS] = {NULL};
|
||||
int sf_n_re, sf_n_samples;
|
||||
|
||||
pthread_t net_thread;
|
||||
pthread_t net_thread;
|
||||
void *net_thread_fnc(void *arg);
|
||||
sem_t net_sem;
|
||||
bool net_packet_ready = false;
|
||||
|
@ -99,7 +101,7 @@ int prbset_orig = 0;
|
|||
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [agmfoncvpu]\n", prog);
|
||||
printf("Usage: %s [agmfoncvpuM]\n", prog);
|
||||
#ifndef DISABLE_RF
|
||||
printf("\t-a RF args [Default %s]\n", rf_args);
|
||||
printf("\t-l RF amplitude [Default %.2f]\n", rf_amp);
|
||||
|
@ -113,13 +115,14 @@ void usage(char *prog) {
|
|||
printf("\t-n number of frames [Default %d]\n", nof_frames);
|
||||
printf("\t-c cell id [Default %d]\n", cell.id);
|
||||
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
|
||||
printf("\t-M Transmission mode[single|diversity|cdd] [Default %s]\n", mimo_type_str);
|
||||
printf("\t-u listen TCP port for input data (-1 is random) [Default %d]\n", net_port);
|
||||
printf("\t-v [set srslte_verbose to debug, default none]\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "aglfmoncpvu")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "aglfmoncpvutM")) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
rf_args = argv[optind];
|
||||
|
@ -151,6 +154,9 @@ void parse_args(int argc, char **argv) {
|
|||
case 'c':
|
||||
cell.id = atoi(argv[optind]);
|
||||
break;
|
||||
case 'M':
|
||||
strncpy(mimo_type_str, argv[optind], 32);
|
||||
break;
|
||||
case 'v':
|
||||
srslte_verbose++;
|
||||
break;
|
||||
|
@ -168,18 +174,54 @@ 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");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Configure cell and PDSCH in function of the transmission mode */
|
||||
switch(pdsch_cfg.mimo_type) {
|
||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||
cell.nof_ports = 1;
|
||||
pdsch_cfg.nof_layers = 1;
|
||||
nof_tb = 1;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
cell.nof_ports = 2;
|
||||
pdsch_cfg.nof_layers = 2;
|
||||
nof_tb = 1;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_CDD:
|
||||
cell.nof_ports = 2;
|
||||
pdsch_cfg.nof_layers = 2;
|
||||
nof_tb = 2;
|
||||
break;
|
||||
default:
|
||||
ERROR("Transmission mode not implemented.");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* init memory */
|
||||
sf_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
|
||||
if (!sf_buffer) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
sf_buffer[i] = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
|
||||
if (!sf_buffer[i]) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
output_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_samples);
|
||||
if (!output_buffer) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
output_buffer[i] = srslte_vec_malloc(sizeof(cf_t) * sf_n_samples);
|
||||
if (!output_buffer[i]) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
}
|
||||
bzero(output_buffer[i], sizeof(cf_t) * sf_n_samples);
|
||||
}
|
||||
|
||||
/* open file or USRP */
|
||||
if (output_file_name) {
|
||||
if (strcmp(output_file_name, "NULL")) {
|
||||
|
@ -194,7 +236,7 @@ void base_init() {
|
|||
} else {
|
||||
#ifndef DISABLE_RF
|
||||
printf("Opening RF device...\n");
|
||||
if (srslte_rf_open(&rf, rf_args)) {
|
||||
if (srslte_rf_open_multi2(&rf, rf_args, cell.nof_ports, 1)) {
|
||||
fprintf(stderr, "Error opening rf\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -247,27 +289,32 @@ void base_init() {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
if (srslte_pdcch_init(&pdcch, ®s, cell)) {
|
||||
if (srslte_pdcch_init_tx(&pdcch, ®s, cell)) {
|
||||
fprintf(stderr, "Error creating PDCCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (srslte_pdsch_init(&pdsch, cell)) {
|
||||
bzero(&pdsch, sizeof(srslte_pdsch_t));
|
||||
if (srslte_pdsch_init_tx_multi(&pdsch, cell)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
srslte_pdsch_set_rnti(&pdsch, UE_CRNTI);
|
||||
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
exit(-1);
|
||||
|
||||
for (i = 0; i < nof_tb; i++) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffers[i], cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void base_free() {
|
||||
|
||||
srslte_softbuffer_tx_free(&softbuffer);
|
||||
int i;
|
||||
for (i = 0; i < nof_tb; i++) {
|
||||
srslte_softbuffer_tx_free(&softbuffers[i]);
|
||||
}
|
||||
srslte_pdsch_free(&pdsch);
|
||||
srslte_pdcch_free(&pdcch);
|
||||
srslte_regs_free(®s);
|
||||
|
@ -275,11 +322,14 @@ void base_free() {
|
|||
|
||||
srslte_ofdm_tx_free(&ifft);
|
||||
|
||||
if (sf_buffer) {
|
||||
free(sf_buffer);
|
||||
}
|
||||
if (output_buffer) {
|
||||
free(output_buffer);
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
if (sf_buffer[i]) {
|
||||
free(sf_buffer[i]);
|
||||
}
|
||||
|
||||
if (output_buffer[i]) {
|
||||
free(output_buffer[i]);
|
||||
}
|
||||
}
|
||||
if (output_file_name) {
|
||||
if (!null_file_sink) {
|
||||
|
@ -340,7 +390,14 @@ int update_radl() {
|
|||
ra_dl.rv_idx = 0;
|
||||
ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
|
||||
ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask();
|
||||
ra_dl.tb_en[0] = 1;
|
||||
ra_dl.tb_en[0] = 1;
|
||||
|
||||
if (nof_tb > 1) {
|
||||
ra_dl.mcs_idx_1 = mcs_idx;
|
||||
ra_dl.ndi_1 = 0;
|
||||
ra_dl.rv_idx_1 = 0;
|
||||
ra_dl.tb_en[1] = 1;
|
||||
}
|
||||
|
||||
srslte_ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
|
||||
srslte_ra_dl_grant_t dummy_grant;
|
||||
|
@ -497,9 +554,9 @@ int main(int argc, char **argv) {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) { // now there's only 1 port
|
||||
sf_symbols[i] = sf_buffer;
|
||||
slot1_symbols[i] = &sf_buffer[SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)];
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
sf_symbols[i] = sf_buffer[i%cell.nof_ports];
|
||||
slot1_symbols[i] = &sf_buffer[i%cell.nof_ports][SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)];
|
||||
}
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
|
@ -556,7 +613,9 @@ int main(int argc, char **argv) {
|
|||
nf = 0;
|
||||
|
||||
bool send_data = false;
|
||||
srslte_softbuffer_tx_reset(&softbuffer);
|
||||
for (i = 0; i < nof_tb; i++) {
|
||||
srslte_softbuffer_tx_reset(&softbuffers[i]);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
bool start_of_burst = true;
|
||||
|
@ -564,15 +623,25 @@ int main(int argc, char **argv) {
|
|||
|
||||
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++) {
|
||||
bzero(sf_buffer, sizeof(cf_t) * sf_n_re);
|
||||
/* Set Antenna port resource elements to zero */
|
||||
bzero(sf_symbols[0], sizeof(cf_t) * sf_n_re);
|
||||
|
||||
/* Populate Synchronization signals if required */
|
||||
if (sf_idx == 0 || sf_idx == 5) {
|
||||
srslte_pss_put_slot(pss_signal, sf_buffer, cell.nof_prb, SRSLTE_CP_NORM);
|
||||
srslte_sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_buffer, cell.nof_prb,
|
||||
srslte_pss_put_slot(pss_signal, sf_symbols[0], cell.nof_prb, SRSLTE_CP_NORM);
|
||||
srslte_sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_symbols[0], cell.nof_prb,
|
||||
SRSLTE_CP_NORM);
|
||||
}
|
||||
|
||||
srslte_refsignal_cs_put_sf(cell, 0, est.csr_signal.pilots[0][sf_idx], sf_buffer);
|
||||
/* Copy zeros, SSS, PSS into the rest of antenna ports */
|
||||
for (i = 1; i < cell.nof_ports; i++) {
|
||||
memcpy(sf_symbols[i], sf_symbols[0], sizeof(cf_t) * sf_n_re);
|
||||
}
|
||||
|
||||
/* Put reference signals */
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_refsignal_cs_put_sf(cell, (uint32_t) i, est.csr_signal.pilots[i / 2][sf_idx], sf_symbols[i]);
|
||||
}
|
||||
|
||||
srslte_pbch_mib_pack(&cell, sfn, bch_payload);
|
||||
if (sf_idx == 0) {
|
||||
|
@ -606,10 +675,23 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (send_data) {
|
||||
|
||||
srslte_dci_format_t dci_format = SRSLTE_DCI_FORMAT1;
|
||||
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:
|
||||
default:
|
||||
fprintf(stderr, "Wrong MIMO configuration\n");
|
||||
exit(SRSLTE_ERROR);
|
||||
}
|
||||
/* Encode PDCCH */
|
||||
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
|
||||
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_msg, cell.nof_prb, cell.nof_ports, false);
|
||||
srslte_dci_msg_pack_pdsch(&ra_dl, dci_format, &dci_msg, cell.nof_prb, cell.nof_ports, false);
|
||||
if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], UE_CRNTI, sf_symbols, sf_idx, cfi)) {
|
||||
fprintf(stderr, "Error encoding DCI message\n");
|
||||
exit(-1);
|
||||
|
@ -618,13 +700,14 @@ int main(int argc, char **argv) {
|
|||
/* 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(&pdsch_cfg, cell, &grant, cfi, sf_idx, 0)) {
|
||||
if (srslte_pdsch_cfg_multi(&pdsch_cfg, cell, &grant, cfi, sf_idx, 0, 0)) {
|
||||
fprintf(stderr, "Error configuring PDSCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Encode PDSCH */
|
||||
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer, data, UE_CRNTI, sf_symbols)) {
|
||||
if (srslte_pdsch_encode_multi(&pdsch, &pdsch_cfg, softbuffers, (uint8_t*[2]){data, data}, UE_CRNTI,
|
||||
sf_symbols)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -641,21 +724,24 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
/* Transform to OFDM symbols */
|
||||
srslte_ofdm_tx_sf(&ifft, sf_buffer, output_buffer);
|
||||
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_ofdm_tx_sf(&ifft, sf_buffer[i], output_buffer[i]);
|
||||
}
|
||||
|
||||
/* send to file or usrp */
|
||||
if (output_file_name) {
|
||||
if (!null_file_sink) {
|
||||
srslte_filesink_write(&fsink, output_buffer, sf_n_samples);
|
||||
srslte_filesink_write_multi(&fsink, (void**) output_buffer, sf_n_samples, cell.nof_ports);
|
||||
}
|
||||
usleep(1000);
|
||||
} else {
|
||||
#ifndef DISABLE_RF
|
||||
// FIXME
|
||||
float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb);
|
||||
srslte_vec_sc_prod_cfc(output_buffer, rf_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
srslte_rf_send2(&rf, output_buffer, sf_n_samples, true, start_of_burst, false);
|
||||
start_of_burst=false;
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
srslte_vec_sc_prod_cfc(output_buffer[i], rf_amp * norm_factor, output_buffer[i], SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
}
|
||||
srslte_rf_send_multi(&rf, (void**) output_buffer, sf_n_samples, true, start_of_burst, false);
|
||||
start_of_burst=false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -258,7 +258,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
|
|||
/**********************************************************************/
|
||||
|
||||
/* TODO: Do something with the output data */
|
||||
uint8_t data[20000];
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS];
|
||||
|
||||
bool go_exit = false;
|
||||
void sig_int_handler(int signo)
|
||||
|
@ -266,10 +266,12 @@ void sig_int_handler(int signo)
|
|||
printf("SIGINT received. Exiting...\n");
|
||||
if (signo == SIGINT) {
|
||||
go_exit = true;
|
||||
} else if (signo == SIGSEGV) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
cf_t *sf_buffer[2] = {NULL, NULL};
|
||||
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) {
|
||||
|
@ -315,6 +317,14 @@ int main(int argc, char **argv) {
|
|||
|
||||
parse_args(&prog_args, argc, argv);
|
||||
|
||||
for (int i = 0; i< SRSLTE_MAX_CODEWORDS; i++) {
|
||||
data[i] = srslte_vec_malloc(sizeof(uint8_t)*1500*8);
|
||||
if (!data[i]) {
|
||||
ERROR("Allocating data");
|
||||
go_exit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(prog_args.cpu_affinity > -1) {
|
||||
|
||||
cpu_set_t cpuset;
|
||||
|
@ -435,8 +445,8 @@ 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(&ue_sync, prog_args.file_nof_prb,
|
||||
prog_args.input_file_name, prog_args.file_offset_time, prog_args.file_offset_freq)) {
|
||||
if (srslte_ue_sync_init_file_multi(&ue_sync, prog_args.file_nof_prb,
|
||||
prog_args.input_file_name, prog_args.file_offset_time, prog_args.file_offset_freq, prog_args.rf_nof_rx_ant)) {
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -498,7 +508,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
// Variables for measurements
|
||||
uint32_t nframes=0;
|
||||
float rsrp=0.0, rsrq=0.0, noise=0.0;
|
||||
float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0;
|
||||
bool decode_pdsch = false;
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
|
@ -596,8 +606,9 @@ int main(int argc, char **argv) {
|
|||
nof_trials++;
|
||||
|
||||
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1);
|
||||
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.05);
|
||||
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05);
|
||||
rsrp0 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 0), rsrp0, 0.05);
|
||||
rsrp1 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 1), rsrp1, 0.05);
|
||||
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05);
|
||||
nframes++;
|
||||
if (isnan(rsrq)) {
|
||||
rsrq = 0;
|
||||
|
@ -605,9 +616,12 @@ int main(int argc, char **argv) {
|
|||
if (isnan(noise)) {
|
||||
noise = 0;
|
||||
}
|
||||
if (isnan(rsrp)) {
|
||||
rsrp = 0;
|
||||
}
|
||||
if (isnan(rsrp0)) {
|
||||
rsrp1 = 0;
|
||||
}
|
||||
if (isnan(rsrp0)) {
|
||||
rsrp1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Plot and Printf
|
||||
|
@ -616,14 +630,27 @@ int main(int argc, char **argv) {
|
|||
if (gain < 0) {
|
||||
gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc));
|
||||
}
|
||||
printf("CFO: %+6.2f kHz, "
|
||||
"SNR: %4.1f dB, "
|
||||
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
|
||||
|
||||
srslte_ue_sync_get_cfo(&ue_sync)/1000,
|
||||
10*log10(rsrp/noise),
|
||||
100*(1-(float) ue_dl.nof_detected/nof_trials),
|
||||
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total);
|
||||
if (cell.nof_ports == 1) {
|
||||
printf("CFO: %+6.2f kHz, "
|
||||
"SNR: %4.1f dB, "
|
||||
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
|
||||
|
||||
srslte_ue_sync_get_cfo(&ue_sync) / 1000,
|
||||
10 * log10(rsrp0 / noise),
|
||||
100 * (1 - (float) ue_dl.nof_detected / nof_trials),
|
||||
(float) 100 * ue_dl.pkt_errors / ue_dl.pkts_total);
|
||||
} else {
|
||||
printf("CFO: %+6.2f kHz, "
|
||||
"SNR port 0: %4.1f dB, "
|
||||
"SNR port 1: %4.1f dB, "
|
||||
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
|
||||
|
||||
srslte_ue_sync_get_cfo(&ue_sync) / 1000,
|
||||
10 * log10(rsrp0 / noise),
|
||||
10 * log10(rsrp1 / noise),
|
||||
100 * (1 - (float) ue_dl.nof_detected / nof_trials),
|
||||
(float) 100 * ue_dl.pkt_errors / ue_dl.pkts_total);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -674,6 +701,16 @@ int main(int argc, char **argv) {
|
|||
#endif
|
||||
srslte_ue_dl_free(&ue_dl);
|
||||
srslte_ue_sync_free(&ue_sync);
|
||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
if (data[i]) {
|
||||
free(data[i]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < prog_args.rf_nof_rx_ant; i++) {
|
||||
if (sf_buffer[i]) {
|
||||
free(sf_buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
if (!prog_args.input_file_name) {
|
||||
|
|
|
@ -44,6 +44,7 @@ char *output_file_name;
|
|||
char *rf_args="";
|
||||
float rf_gain=40.0, rf_freq=-1.0, rf_rate=0.96e6;
|
||||
int nof_samples = -1;
|
||||
int nof_rx_antennas = 1;
|
||||
|
||||
void int_handler(int dummy) {
|
||||
keep_running = false;
|
||||
|
@ -55,12 +56,13 @@ void usage(char *prog) {
|
|||
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
|
||||
printf("\t-r RF Rate [Default %.6f Hz]\n", rf_rate);
|
||||
printf("\t-n nof_samples [Default %d]\n", nof_samples);
|
||||
printf("\t-A nof_rx_antennas [Default %d]\n", nof_rx_antennas);
|
||||
printf("\t-v srslte_verbose\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "agrnvfo")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "agrnvfoA")) != -1) {
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
output_file_name = argv[optind];
|
||||
|
@ -80,6 +82,9 @@ void parse_args(int argc, char **argv) {
|
|||
case 'n':
|
||||
nof_samples = atoi(argv[optind]);
|
||||
break;
|
||||
case 'A':
|
||||
nof_rx_antennas = atoi(argv[optind]);
|
||||
break;
|
||||
case 'v':
|
||||
srslte_verbose++;
|
||||
break;
|
||||
|
@ -95,11 +100,11 @@ void parse_args(int argc, char **argv) {
|
|||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
cf_t *buffer;
|
||||
cf_t *buffer[SRSLTE_MAX_PORTS];
|
||||
int sample_count, n;
|
||||
srslte_rf_t rf;
|
||||
srslte_filesink_t sink;
|
||||
int32_t buflen;
|
||||
uint32_t buflen;
|
||||
|
||||
signal(SIGINT, int_handler);
|
||||
|
||||
|
@ -107,17 +112,19 @@ int main(int argc, char **argv) {
|
|||
|
||||
buflen = 4800;
|
||||
sample_count = 0;
|
||||
|
||||
buffer = malloc(sizeof(cf_t) * buflen);
|
||||
if (!buffer) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
|
||||
for (int i = 0; i < nof_rx_antennas; i++) {
|
||||
buffer[i] = malloc(sizeof(cf_t) * buflen);
|
||||
if (!buffer[i]) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
|
||||
|
||||
printf("Opening RF device...\n");
|
||||
if (srslte_rf_open(&rf, rf_args)) {
|
||||
if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
|
||||
fprintf(stderr, "Error opening rf\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -151,18 +158,23 @@ int main(int argc, char **argv) {
|
|||
|
||||
while((sample_count < nof_samples || nof_samples == -1)
|
||||
&& keep_running){
|
||||
n = srslte_rf_recv(&rf, buffer, buflen, 1);
|
||||
n = srslte_rf_recv_with_time_multi(&rf, (void**) buffer, buflen, true, NULL, NULL);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error receiving samples\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
srslte_filesink_write(&sink, buffer, buflen);
|
||||
srslte_filesink_write_multi(&sink, (void**) buffer, buflen, nof_rx_antennas);
|
||||
sample_count += buflen;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nof_rx_antennas; i++) {
|
||||
if (buffer[i]) {
|
||||
free(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
srslte_filesink_free(&sink);
|
||||
free(buffer);
|
||||
srslte_rf_close(&rf);
|
||||
|
||||
printf("Ok - wrote %d samples\n", sample_count);
|
||||
|
|
|
@ -45,6 +45,7 @@ float rf_gain=60.0, rf_freq=-1.0;
|
|||
int nof_prb = 6;
|
||||
int nof_subframes = -1;
|
||||
int N_id_2 = -1;
|
||||
uint32_t nof_rx_antennas = 1;
|
||||
|
||||
void int_handler(int dummy) {
|
||||
keep_running = false;
|
||||
|
@ -56,12 +57,13 @@ void usage(char *prog) {
|
|||
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
|
||||
printf("\t-p nof_prb [Default %d]\n", nof_prb);
|
||||
printf("\t-n nof_subframes [Default %d]\n", nof_subframes);
|
||||
printf("\t-A nof_rx_antennas [Default %d]\n", nof_rx_antennas);
|
||||
printf("\t-v verbose\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "agpnvfol")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "agpnvfolA")) != -1) {
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
output_file_name = argv[optind];
|
||||
|
@ -84,6 +86,9 @@ void parse_args(int argc, char **argv) {
|
|||
case 'l':
|
||||
N_id_2 = atoi(argv[optind]);
|
||||
break;
|
||||
case 'A':
|
||||
nof_rx_antennas = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'v':
|
||||
srslte_verbose++;
|
||||
break;
|
||||
|
@ -100,7 +105,7 @@ 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(h, data[0], nsamples, 1);
|
||||
return srslte_rf_recv_with_time_multi(h, (void**) data, nsamples, true, NULL, NULL);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
@ -118,13 +123,15 @@ int main(int argc, char **argv) {
|
|||
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
|
||||
|
||||
printf("Opening RF device...\n");
|
||||
if (srslte_rf_open(&rf, rf_args)) {
|
||||
if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
|
||||
fprintf(stderr, "Error opening rf\n");
|
||||
exit(-1);
|
||||
}
|
||||
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
|
||||
|
||||
buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
|
||||
for (int i = 0; i< SRSLTE_MAX_PORTS; i++) {
|
||||
buffer[i] = srslte_vec_malloc(3 * sizeof(cf_t) * SRSLTE_SF_LEN_PRB(100));
|
||||
}
|
||||
|
||||
sigset_t sigset;
|
||||
sigemptyset(&sigset);
|
||||
|
@ -158,7 +165,7 @@ int main(int argc, char **argv) {
|
|||
cell.nof_prb = nof_prb;
|
||||
cell.nof_ports = 1;
|
||||
|
||||
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
|
||||
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, nof_rx_antennas, (void*) &rf)) {
|
||||
fprintf(stderr, "Error initiating ue_sync\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -181,7 +188,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
} else {
|
||||
printf("Writing to file %6d subframes...\r", subframe_count);
|
||||
srslte_filesink_write(&sink, buffer[0], SRSLTE_SF_LEN_PRB(nof_prb));
|
||||
srslte_filesink_write_multi(&sink, (void**) buffer, SRSLTE_SF_LEN_PRB(nof_prb),nof_rx_antennas);
|
||||
subframe_count++;
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +203,12 @@ 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++) {
|
||||
if (buffer[i]) {
|
||||
free(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Ok - wrote %d subframes\n", subframe_count);
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -132,6 +132,9 @@ 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_rsrp_port(srslte_chest_dl_t *q,
|
||||
uint32_t port);
|
||||
|
||||
SRSLTE_API float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -244,6 +244,8 @@ SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old,
|
|||
|
||||
SRSLTE_API char *srslte_cp_string(srslte_cp_t cp);
|
||||
|
||||
SRSLTE_API srslte_mod_t srslte_str2mod (char * mod_str);
|
||||
|
||||
SRSLTE_API char *srslte_mod_string(srslte_mod_t mod);
|
||||
|
||||
SRSLTE_API uint32_t srslte_mod_bits_x_symbol(srslte_mod_t mod);
|
||||
|
|
|
@ -59,4 +59,9 @@ SRSLTE_API int srslte_filesink_write(srslte_filesink_t *q,
|
|||
void *buffer,
|
||||
int nsamples);
|
||||
|
||||
SRSLTE_API int srslte_filesink_write_multi(srslte_filesink_t *q,
|
||||
void **buffer,
|
||||
int nsamples,
|
||||
int nchannels);
|
||||
|
||||
#endif // FILESINK_
|
||||
|
|
|
@ -62,4 +62,9 @@ SRSLTE_API int srslte_filesource_read(srslte_filesource_t *q,
|
|||
void *buffer,
|
||||
int nsamples);
|
||||
|
||||
SRSLTE_API int srslte_filesource_read_multi(srslte_filesource_t *q,
|
||||
void **buffer,
|
||||
int nsamples,
|
||||
int nof_channels);
|
||||
|
||||
#endif // FILESOURCE_
|
||||
|
|
|
@ -88,11 +88,26 @@ SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q,
|
|||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init_tx(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init_rx(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init_multi(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init_txrx(srslte_pdcch_t *q,
|
||||
srslte_regs_t *regs,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas,
|
||||
bool isReceiver);
|
||||
|
||||
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q);
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
typedef struct {
|
||||
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
srslte_sequence_t seq2[SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
bool sequence_generated;
|
||||
} srslte_pdsch_user_t;
|
||||
|
||||
|
@ -62,11 +63,13 @@ typedef struct SRSLTE_API {
|
|||
|
||||
/* buffers */
|
||||
// void buffers are shared for tx and rx
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
cf_t *symbols[SRSLTE_MAX_PORTS];
|
||||
cf_t *x[SRSLTE_MAX_PORTS];
|
||||
cf_t *d;
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
|
||||
cf_t *symbols[SRSLTE_MAX_PORTS]; /* PDSCH Encoded/Decoded Symbols */
|
||||
cf_t *x[SRSLTE_MAX_LAYERS]; /* Layer mapped */
|
||||
cf_t *d; /* Modulated/Demodulated codeword 1 */
|
||||
cf_t *d2; /* Modulated/Demodulated codeword 2 */
|
||||
void *e;
|
||||
void *e2;
|
||||
|
||||
/* tx & rx objects */
|
||||
srslte_modem_table_t mod[4];
|
||||
|
@ -81,9 +84,12 @@ typedef struct SRSLTE_API {
|
|||
SRSLTE_API int srslte_pdsch_init(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_init_multi(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_rx_antennas);
|
||||
SRSLTE_API int srslte_pdsch_init_tx_multi(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_init_rx_multi(srslte_pdsch_t *q,
|
||||
srslte_cell_t cell,
|
||||
uint32_t nof_antennas);
|
||||
|
||||
SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q);
|
||||
|
||||
|
@ -103,6 +109,14 @@ SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg,
|
|||
uint32_t sf_idx,
|
||||
uint32_t rvidx);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg,
|
||||
srslte_cell_t cell,
|
||||
srslte_ra_dl_grant_t *grant,
|
||||
uint32_t cfi,
|
||||
uint32_t sf_idx,
|
||||
uint32_t rvidx,
|
||||
uint32_t rvidx2);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_tx_t *softbuffer,
|
||||
|
@ -110,6 +124,13 @@ SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t *q,
|
|||
uint16_t rnti,
|
||||
cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
|
||||
|
||||
SRSLTE_API int srslte_pdsch_encode_multi(srslte_pdsch_t *q,
|
||||
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_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_rx_t *softbuffer,
|
||||
|
@ -121,12 +142,12 @@ SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t *q,
|
|||
|
||||
SRSLTE_API int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_rx_t *softbuffer,
|
||||
srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS],
|
||||
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);
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS]);
|
||||
|
||||
SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q);
|
||||
|
||||
|
|
|
@ -41,10 +41,15 @@
|
|||
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_cbsegm_t cb_segm;
|
||||
srslte_cbsegm_t cb_segm2;
|
||||
srslte_ra_dl_grant_t grant;
|
||||
srslte_ra_nbits_t nbits;
|
||||
srslte_ra_nbits_t nbits2;
|
||||
uint32_t rv;
|
||||
uint32_t rv2;
|
||||
uint32_t sf_idx;
|
||||
uint32_t nof_layers;
|
||||
srslte_mimo_type_t mimo_type;
|
||||
} srslte_pdsch_cfg_t;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -209,6 +209,13 @@ SRSLTE_API void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant,
|
|||
uint32_t sf_idx,
|
||||
srslte_ra_nbits_t *nbits);
|
||||
|
||||
SRSLTE_API void srslte_ra_dl_grant_to_nbits_multi(srslte_ra_dl_grant_t *grant,
|
||||
uint32_t cfi,
|
||||
srslte_cell_t cell,
|
||||
uint32_t sf_idx,
|
||||
srslte_ra_nbits_t *nbits,
|
||||
srslte_ra_nbits_t *nbits2);
|
||||
|
||||
SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell,
|
||||
uint32_t nof_prb,
|
||||
uint32_t nof_ctrl_symbols);
|
||||
|
|
|
@ -96,12 +96,24 @@ SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q,
|
|||
uint8_t *data,
|
||||
uint8_t *e_bits);
|
||||
|
||||
SRSLTE_API int srslte_dlsch_encode_multi(srslte_sch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS],
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS],
|
||||
uint8_t *e_bits[SRSLTE_MAX_CODEWORDS]);
|
||||
|
||||
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_multi(srslte_sch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg,
|
||||
srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS],
|
||||
int16_t *e_bits[SRSLTE_MAX_CODEWORDS],
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS]);
|
||||
|
||||
SRSLTE_API int srslte_ulsch_encode(srslte_sch_t *q,
|
||||
srslte_pusch_cfg_t *cfg,
|
||||
srslte_softbuffer_tx_t *softbuffer,
|
||||
|
|
|
@ -75,6 +75,11 @@ SRSLTE_API int srslte_rf_open_multi(srslte_rf_t *h,
|
|||
char *args,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_rf_open_multi2(srslte_rf_t *h,
|
||||
char *args,
|
||||
uint32_t nof_tx_antennas,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_rf_open_devname(srslte_rf_t *h,
|
||||
char *devname,
|
||||
char *args);
|
||||
|
@ -84,6 +89,12 @@ SRSLTE_API int srslte_rf_open_devname_multi(srslte_rf_t *h,
|
|||
char *args,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API int srslte_rf_open_devname_multi2(srslte_rf_t *rf,
|
||||
char *devname,
|
||||
char *args,
|
||||
uint32_t nof_tx_antennas,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API const char *srslte_rf_name(srslte_rf_t *h);
|
||||
|
||||
SRSLTE_API int srslte_rf_start_gain_thread(srslte_rf_t *rf,
|
||||
|
@ -200,5 +211,12 @@ SRSLTE_API int srslte_rf_send_timed2(srslte_rf_t *h,
|
|||
bool is_start_of_burst,
|
||||
bool is_end_of_burst);
|
||||
|
||||
SRSLTE_API int srslte_rf_send_multi(srslte_rf_t *rf,
|
||||
void *data[4],
|
||||
int nsamples,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ typedef struct SRSLTE_API {
|
|||
srslte_cfo_t sfo_correct;
|
||||
|
||||
srslte_pdsch_cfg_t pdsch_cfg;
|
||||
srslte_softbuffer_rx_t softbuffer;
|
||||
srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS];
|
||||
srslte_ra_dl_dci_t dl_dci;
|
||||
srslte_cell_t cell;
|
||||
|
||||
|
@ -142,6 +142,13 @@ SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
|
|||
uint32_t sf_idx,
|
||||
uint32_t rvidx);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q,
|
||||
srslte_ra_dl_grant_t *grant,
|
||||
uint32_t cfi,
|
||||
uint32_t sf_idx,
|
||||
uint32_t rvidx,
|
||||
uint32_t rvidx2);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q,
|
||||
uint32_t cfi,
|
||||
uint32_t sf_idx,
|
||||
|
@ -173,7 +180,7 @@ SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q,
|
|||
|
||||
SRSLTE_API int srslte_ue_dl_decode_multi(srslte_ue_dl_t * q,
|
||||
cf_t *input[SRSLTE_MAX_PORTS],
|
||||
uint8_t *data,
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS],
|
||||
uint32_t tti);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t * q,
|
||||
|
@ -184,7 +191,7 @@ SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t * q,
|
|||
|
||||
SRSLTE_API int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t * q,
|
||||
cf_t *input[SRSLTE_MAX_PORTS],
|
||||
uint8_t *data,
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS],
|
||||
uint32_t tti,
|
||||
uint16_t rnti);
|
||||
|
||||
|
|
|
@ -148,6 +148,13 @@ SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q,
|
|||
int offset_time,
|
||||
float offset_freq);
|
||||
|
||||
SRSLTE_API int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q,
|
||||
uint32_t nof_prb,
|
||||
char *file_name,
|
||||
int offset_time,
|
||||
float offset_freq,
|
||||
uint32_t nof_rx_ant);
|
||||
|
||||
SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q);
|
||||
|
||||
SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
|
||||
|
|
|
@ -63,5 +63,6 @@ SRSLTE_API extern int srslte_verbose;
|
|||
#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO) \
|
||||
fprintf(stdout, "[INFO]: " _fmt, __VA_ARGS__)
|
||||
|
||||
#define ERROR(_fmt) fprintf(stderr, "%s.%d: " _fmt "\n", __FILE__, __LINE__)
|
||||
|
||||
#endif // DEBUG_H
|
||||
|
|
|
@ -417,12 +417,15 @@ float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q) {
|
|||
|
||||
}
|
||||
|
||||
float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) {
|
||||
// Note: use only port 0 but average across antennas
|
||||
float n = 0;
|
||||
for (int i=0;i<q->last_nof_antennas;i++) {
|
||||
n += q->rsrp[i][0];
|
||||
float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) {
|
||||
float n = 0;
|
||||
for (int i = 0; i < q->last_nof_antennas; i++) {
|
||||
n += q->rsrp[i][port];
|
||||
}
|
||||
return n/q->last_nof_antennas;
|
||||
return n / q->last_nof_antennas;
|
||||
}
|
||||
|
||||
float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) {
|
||||
// Note: use only port 0 but average across antennas
|
||||
return srslte_chest_dl_get_rsrp_port(q, 0);
|
||||
}
|
||||
|
|
|
@ -52,4 +52,3 @@ add_test(chest_test_ul_cellid1 chest_test_ul -c 2 -r 50)
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -124,6 +124,19 @@ bool srslte_N_id_1_isvalid(uint32_t N_id_1) {
|
|||
}
|
||||
}
|
||||
|
||||
srslte_mod_t srslte_str2mod (char * mod_str) {
|
||||
if (!strcmp(mod_str, "QPSK")) {
|
||||
return SRSLTE_MOD_QPSK;
|
||||
} else if (!strcmp(mod_str, "16QAM")) {
|
||||
return SRSLTE_MOD_16QAM;
|
||||
} else if (!strcmp(mod_str, "64QAM")) {
|
||||
return SRSLTE_MOD_64QAM;
|
||||
} else {
|
||||
return (srslte_mod_t) SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
char *srslte_mod_string(srslte_mod_t mod) {
|
||||
switch (mod) {
|
||||
case SRSLTE_MOD_BPSK:
|
||||
|
@ -419,12 +432,14 @@ struct lte_band lte_bands[SRSLTE_NOF_LTE_BANDS] = {
|
|||
|
||||
|
||||
int srslte_str2mimotype(char *mimo_type_str, srslte_mimo_type_t *type) {
|
||||
if (!strcmp(mimo_type_str, "single")) {
|
||||
if (!strcmp(mimo_type_str, "single") || !strcmp(mimo_type_str, "Port0")) {
|
||||
*type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||
} else if (!strcmp(mimo_type_str, "diversity")) {
|
||||
} 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")) {
|
||||
*type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||
} else if (!strcmp(mimo_type_str, "cdd") || !strcmp(mimo_type_str, "CDD")) {
|
||||
*type = SRSLTE_MIMO_TYPE_CDD;
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
|
|
@ -99,3 +99,60 @@ int srslte_filesink_write(srslte_filesink_t *q, void *buffer, int nsamples) {
|
|||
return i;
|
||||
}
|
||||
|
||||
int srslte_filesink_write_multi(srslte_filesink_t *q, void **buffer, int nsamples, int nchannels) {
|
||||
int i, j;
|
||||
float **fbuf = (float**) buffer;
|
||||
_Complex float **cbuf = (_Complex float**) buffer;
|
||||
_Complex short **sbuf = (_Complex short**) buffer;
|
||||
int size;
|
||||
|
||||
switch(q->type) {
|
||||
case SRSLTE_FLOAT:
|
||||
for (i=0;i<nsamples;i++) {
|
||||
for (j=0;j<nchannels;j++) {
|
||||
fprintf(q->f, "%g%c", fbuf[j][i], (j!=(nchannels-1))?'\t':'\n');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SRSLTE_COMPLEX_FLOAT:
|
||||
for (i=0;i<nsamples;i++) {
|
||||
for (j=0;j<nchannels;j++) {
|
||||
fprintf(q->f, "%g%+gi%c", __real__ cbuf[j][i], __imag__ cbuf[j][i], (j!=(nchannels-1))?'\t':'\n');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SRSLTE_COMPLEX_SHORT:
|
||||
for (i=0;i<nsamples;i++) {
|
||||
for (j=0;j<nchannels;j++) {
|
||||
fprintf(q->f, "%hd%+hdi%c", __real__ sbuf[j][i], __imag__ sbuf[j][i], (j!=(nchannels-1))?'\t':'\n');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SRSLTE_FLOAT_BIN:
|
||||
case SRSLTE_COMPLEX_FLOAT_BIN:
|
||||
case SRSLTE_COMPLEX_SHORT_BIN:
|
||||
if (q->type == SRSLTE_FLOAT_BIN) {
|
||||
size = sizeof(float);
|
||||
} else if (q->type == SRSLTE_COMPLEX_FLOAT_BIN) {
|
||||
size = sizeof(_Complex float);
|
||||
} else if (q->type == SRSLTE_COMPLEX_SHORT_BIN) {
|
||||
size = sizeof(_Complex short);
|
||||
}
|
||||
if (nchannels > 1) {
|
||||
uint32_t count = 0;
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
for (j = 0; j < nchannels; j++) {
|
||||
count += fwrite(&cbuf[j][i], size, 1, q->f);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
} else {
|
||||
return fwrite(buffer[0], size, nsamples, q->f);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
|
@ -116,3 +116,29 @@ int srslte_filesource_read(srslte_filesource_t *q, void *buffer, int nsamples) {
|
|||
return i;
|
||||
}
|
||||
|
||||
int srslte_filesource_read_multi(srslte_filesource_t *q, void **buffer, int nsamples, int nof_channels) {
|
||||
int i, j, count = 0;
|
||||
_Complex float **cbuf = (_Complex float **) buffer;
|
||||
|
||||
switch (q->type) {
|
||||
case SRSLTE_FLOAT:
|
||||
case SRSLTE_COMPLEX_FLOAT:
|
||||
case SRSLTE_COMPLEX_SHORT:
|
||||
case SRSLTE_FLOAT_BIN:
|
||||
case SRSLTE_COMPLEX_SHORT_BIN:
|
||||
fprintf(stderr, "%s.%d:Read Mode not implemented\n", __FILE__, __LINE__);
|
||||
count = SRSLTE_ERROR;
|
||||
break;
|
||||
case SRSLTE_COMPLEX_FLOAT_BIN:
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
for (j = 0; j < nof_channels; j++) {
|
||||
count += fread(&cbuf[j][i], sizeof(cf_t), (size_t) 1, q->f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
count = SRSLTE_ERROR;
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
}
|
|
@ -530,6 +530,154 @@ int srslte_predecoding_type(cf_t *y_, cf_t *h_[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE
|
|||
return srslte_predecoding_type_multi(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols, type, noise_estimate);
|
||||
}
|
||||
|
||||
|
||||
int srslte_precoding_mimo_2x2_gen(cf_t W[2][2], cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_symbols, float noise_estimate)
|
||||
{
|
||||
|
||||
cf_t G[2][2], Gx[2][2];
|
||||
|
||||
for (int i=0; i<nof_symbols; i++) {
|
||||
|
||||
// G=H*W
|
||||
G[0][0] = h[0][0][i]*W[0][0]+h[0][1][i]*W[1][0];
|
||||
G[0][1] = h[0][0][i]*W[1][0]+h[0][1][i]*W[1][1];
|
||||
G[1][0] = h[1][0][i]*W[0][0]+h[1][1][i]*W[1][0];
|
||||
G[1][1] = h[1][0][i]*W[1][0]+h[1][1][i]*W[1][1];
|
||||
|
||||
if (noise_estimate == 0) {
|
||||
// MF equalizer: Gx = G'
|
||||
Gx[0][0] = conjf(G[0][0]);
|
||||
Gx[0][1] = conjf(G[1][0]);
|
||||
Gx[1][0] = conjf(G[0][1]);
|
||||
Gx[1][1] = conjf(G[1][1]);
|
||||
} else {
|
||||
// MMSE equalizer: Gx = (G'G+I)
|
||||
fprintf(stderr, "MMSE MIMO decoder not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// x=G*y
|
||||
x[0][i] = Gx[0][0]*y[0][i] + Gx[0][1]*y[1][i];
|
||||
x[1][i] = Gx[1][0]*y[0][i] + Gx[1][1]*y[1][i];
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// SSE implementation of ZF 2x2 CCD equalizer
|
||||
#ifdef LV_HAVE_SSE
|
||||
|
||||
int srslte_predecoding_ccd_2x2_zf_sse(cf_t *y[SRSLTE_MAX_PORTS],
|
||||
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
uint32_t nof_symbols) {
|
||||
uint32_t i = 0;
|
||||
|
||||
/* Conjugate mask */
|
||||
__m128 conj_mask = (__m128) {+0.0f, -0.0f, +0.0f, -0.0f};
|
||||
|
||||
for (i = 0; i < nof_symbols; i += 2) {
|
||||
/* Load channel */
|
||||
__m128 h00i = _mm_load_ps((float *) &h[0][0][i]);
|
||||
__m128 h01i = _mm_load_ps((float *) &h[0][1][i]);
|
||||
__m128 h10i = _mm_load_ps((float *) &h[1][0][i]);
|
||||
__m128 h11i = _mm_load_ps((float *) &h[1][1][i]);
|
||||
|
||||
/* Apply precoding */
|
||||
__m128 h00 = _mm_add_ps(h00i, _mm_xor_ps(h10i, (__m128) {+0.0f, +0.0f, -0.0f, -0.0f}));
|
||||
__m128 h10 = _mm_add_ps(h01i, _mm_xor_ps(h11i, (__m128) {+0.0f, +0.0f, -0.0f, -0.0f}));
|
||||
__m128 h01 = _mm_add_ps(h00i, _mm_xor_ps(h10i, (__m128) {-0.0f, -0.0f, +0.0f, +0.0f}));
|
||||
__m128 h11 = _mm_add_ps(h01i, _mm_xor_ps(h11i, (__m128) {-0.0f, -0.0f, +0.0f, +0.0f}));
|
||||
|
||||
__m128 detmult1 = PROD(h00, h11);
|
||||
__m128 detmult2 = PROD(h01, h10);
|
||||
|
||||
__m128 det = _mm_sub_ps(detmult1, detmult2);
|
||||
__m128 detconj = _mm_xor_ps(det, conj_mask);
|
||||
__m128 detabs2 = PROD(det, detconj);
|
||||
__m128 detabs2rec = _mm_rcp_ps(detabs2);
|
||||
detabs2rec = _mm_shuffle_ps(detabs2rec, detabs2rec, _MM_SHUFFLE(2, 2, 0, 0));
|
||||
__m128 detrec = _mm_mul_ps(_mm_mul_ps(detconj, detabs2rec), (__m128) {2.0f, 2.0f, 2.0f, 2.0f});
|
||||
|
||||
__m128 y0 = _mm_load_ps((float *) &y[0][i]);
|
||||
__m128 y1 = _mm_load_ps((float *) &y[1][i]);
|
||||
|
||||
__m128 x0 = PROD(_mm_sub_ps(PROD(h11, y0), PROD(h01, y1)), detrec);
|
||||
__m128 x1 = PROD(_mm_sub_ps(PROD(h00, y1), PROD(h10, y0)), detrec);
|
||||
|
||||
_mm_store_ps((float *) &x[0][i], x0);
|
||||
_mm_store_ps((float *) &x[1][i], x1);
|
||||
}
|
||||
|
||||
return nof_symbols;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Generic implementation of ZF 2x2 CCD equalizer
|
||||
int srslte_predecoding_ccd_2x2_zf_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_symbols) {
|
||||
cf_t h00, h01, h10, h11, det;
|
||||
for (int i = 0; i < nof_symbols; i++) {
|
||||
|
||||
// Even precoder
|
||||
h00 = +h[0][0][i] + h[1][0][i];
|
||||
h10 = +h[0][1][i] + h[1][1][i];
|
||||
h01 = +h[0][0][i] - h[1][0][i];
|
||||
h11 = +h[0][1][i] - h[1][1][i];
|
||||
det = (h00 * h11 - h01 * h10);
|
||||
det = conjf(det) * ((float) 2.0 / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det)));
|
||||
|
||||
x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det;
|
||||
x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det;
|
||||
|
||||
i++;
|
||||
|
||||
// Odd precoder
|
||||
h00 = h[0][0][i] - h[1][0][i];
|
||||
h10 = h[0][1][i] - h[1][1][i];
|
||||
h01 = h[0][0][i] + h[1][0][i];
|
||||
h11 = h[0][1][i] + h[1][1][i];
|
||||
det = (h00 * h11 - h01 * h10);
|
||||
det = conjf(det) * ((float) 2.0 / (crealf(det) * crealf(det) + cimagf(det) * cimagf(det)));
|
||||
|
||||
x[0][i] = (+h11 * y[0][i] - h01 * y[1][i]) * det;
|
||||
x[1][i] = (-h10 * y[0][i] + h00 * y[1][i]) * det;
|
||||
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srslte_predecoding_ccd_zf(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_rxant, int nof_ports, int nof_layers, int nof_symbols)
|
||||
{
|
||||
if (nof_ports == 2 && nof_rxant == 2) {
|
||||
if (nof_layers == 2) {
|
||||
#ifdef LV_HAVE_SSE
|
||||
return srslte_predecoding_ccd_2x2_zf_sse(y, h, x, nof_symbols);
|
||||
#else
|
||||
return srslte_predecoding_ccd_2x2_zf_gen(y, h, x, nof_symbols);
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, "Error predecoding CCD: Invalid number of layers %d\n", nof_layers);
|
||||
return -1;
|
||||
}
|
||||
} else if (nof_ports == 4) {
|
||||
fprintf(stderr, "Error predecoding CCD: Only 2 ports supported\n");
|
||||
} else {
|
||||
fprintf(stderr, "Error predecoding CCD: Invalid combination of ports %d and rx antennax %d\n", nof_ports, nof_rxant);
|
||||
}
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 36.211 v10.3.0 Section 6.3.4 */
|
||||
int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_rxant, int nof_ports, int nof_layers, int nof_symbols, srslte_mimo_type_t type, float noise_estimate) {
|
||||
|
@ -547,7 +695,13 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_
|
|||
|
||||
switch (type) {
|
||||
case SRSLTE_MIMO_TYPE_CDD:
|
||||
fprintf(stderr, "CCD not supported\n");
|
||||
if (nof_layers >= 2 && nof_layers <= 4) {
|
||||
return srslte_predecoding_ccd_zf(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Invalid number of layers %d\n", nof_layers);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||
if (nof_ports == 1 && nof_layers == 1) {
|
||||
|
|
|
@ -42,7 +42,7 @@ add_test(layermap_multiplex_24 layermap_test -n 1000 -m multiplex -c 2 -l 4)
|
|||
|
||||
|
||||
########################################################################
|
||||
# LAYER MAPPING TEST
|
||||
# PRECODING MAPPING TEST
|
||||
########################################################################
|
||||
|
||||
add_executable(precoding_test precoder_test.c)
|
||||
|
@ -52,6 +52,7 @@ add_test(precoding_single precoding_test -n 1000 -m single)
|
|||
add_test(precoding_diversity2 precoding_test -n 1000 -m diversity -l 2 -p 2)
|
||||
add_test(precoding_diversity4 precoding_test -n 1024 -m diversity -l 4 -p 4)
|
||||
|
||||
add_test(precoding_cdd_2x2 precoding_test -m cdd -l 2 -p 2 -r 2)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ int nof_cw = 1, nof_layers = 1;
|
|||
char *mimo_type_name = NULL;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s -m [single|diversity|multiplex] -c [nof_cw] -l [nof_layers]\n", prog);
|
||||
printf("Usage: %s -m [single|diversity|multiplex|cdd] -c [nof_cw] -l [nof_layers]\n", prog);
|
||||
printf("\t-n num_symbols [Default %d]\n", nof_symbols);
|
||||
}
|
||||
|
||||
|
|
|
@ -78,9 +78,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
x[i] = srslte_vec_malloc(sizeof(cf_t)*nof_symbols/nof_layers);
|
||||
}
|
||||
|
||||
output = srslte_vec_malloc(sizeof(cf_t)*nof_symbols*nof_tx_ports/nof_layers);
|
||||
output = srslte_vec_malloc(sizeof(cf_t)*nof_symbols*nof_tx_ports);
|
||||
for (int i=0;i<nof_tx_ports;i++) {
|
||||
y[i] = &output[i*nof_symbols/nof_layers];
|
||||
y[i] = &output[i*nof_symbols];
|
||||
}
|
||||
|
||||
char *txscheme = "Port0";
|
||||
|
@ -102,13 +102,30 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
int symbols_layers[SRSLTE_MAX_LAYERS];
|
||||
for (int i=0;i<nof_layers;i++) {
|
||||
symbols_layers[i] = nof_symbols/nof_layers;
|
||||
symbols_layers[i] = nof_symbols;
|
||||
}
|
||||
srslte_layermap_type(d, x, nof_codewords, nof_layers, symbols_layers, type);
|
||||
srslte_precoding_type(x, y, nof_layers, nof_tx_ports, nof_symbols/nof_layers, type);
|
||||
|
||||
if (nlhs >= 1) {
|
||||
mexutils_write_cf(output, &plhs[0], nof_symbols/nof_layers, nof_tx_ports);
|
||||
switch (type) {
|
||||
case SRSLTE_MIMO_TYPE_CDD:
|
||||
mexutils_write_cf(output, &plhs[0], nof_symbols/nof_layers, nof_tx_ports);
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
|
||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||
default:
|
||||
mexutils_write_cf(output, &plhs[0], (uint32_t) nof_symbols, nof_tx_ports);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nlhs >= 2) {
|
||||
mexutils_write_cf(x[0], &plhs[1], nof_symbols / nof_layers, 1);
|
||||
}
|
||||
if (nlhs >= 3) {
|
||||
mexutils_write_cf(x[1], &plhs[2], nof_symbols / nof_layers, 1);
|
||||
}
|
||||
|
||||
if (input) {
|
||||
|
|
|
@ -35,28 +35,31 @@
|
|||
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
#define MSE_THRESHOLD 0.00001
|
||||
#define MSE_THRESHOLD 0.0005
|
||||
|
||||
int nof_symbols = 1000;
|
||||
int nof_layers = 1, nof_ports = 1;
|
||||
int nof_layers = 1, nof_tx_ports = 1, nof_rx_ports = 1, nof_re = 1;
|
||||
char *mimo_type_name = NULL;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf(
|
||||
"Usage: %s -m [single|diversity|multiplex] -l [nof_layers] -p [nof_ports]\n",
|
||||
prog);
|
||||
"Usage: %s -m [single|diversity|multiplex|cdd] -l [nof_layers] -p [nof_tx_ports]\n"
|
||||
" -r [nof_rx_ports]\n", prog);
|
||||
printf("\t-n num_symbols [Default %d]\n", nof_symbols);
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "mpln")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "mplnr")) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
nof_symbols = atoi(argv[optind]);
|
||||
break;
|
||||
case 'p':
|
||||
nof_ports = atoi(argv[optind]);
|
||||
nof_tx_ports = atoi(argv[optind]);
|
||||
break;
|
||||
case 'r':
|
||||
nof_rx_ports = atoi(argv[optind]);
|
||||
break;
|
||||
case 'l':
|
||||
nof_layers = atoi(argv[optind]);
|
||||
|
@ -75,102 +78,175 @@ void parse_args(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
void populate_channel_cdd(cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], uint32_t n) {
|
||||
int i, j, k;
|
||||
|
||||
for (i = 0; i < nof_tx_ports; i++) {
|
||||
for (j = 0; j < nof_rx_ports; j++) {
|
||||
for (k = 0; k < n; k++) {
|
||||
h[i][j][k] = (float) rand() / RAND_MAX + ((float) rand() / RAND_MAX) * _Complex_I;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void populate_channel_diversity(cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], uint32_t n) {
|
||||
int i, j, k, l;
|
||||
|
||||
for (i = 0; i < nof_tx_ports; i++) {
|
||||
for (j = 0; j < nof_rx_ports; j++) {
|
||||
for (k = 0; k < n / nof_layers; k++) {
|
||||
cf_t hsymb = (float) rand() / RAND_MAX + ((float) rand() / RAND_MAX) * _Complex_I;
|
||||
for (l = 0; l < nof_layers; l++) {
|
||||
// assume the channel is the same for all symbols
|
||||
h[i][j][k * nof_layers + l] = hsymb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void populate_channel_single(cf_t *h) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nof_re; i++) {
|
||||
h[i] = (float) rand() / RAND_MAX + ((float) rand() / RAND_MAX) * _Complex_I;
|
||||
}
|
||||
}
|
||||
|
||||
void populate_channel(srslte_mimo_type_t type, cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]) {
|
||||
switch (type) {
|
||||
case SRSLTE_MIMO_TYPE_CDD:
|
||||
populate_channel_cdd(h, (uint32_t) nof_re);
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
populate_channel_diversity(h, (uint32_t) nof_re);
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
|
||||
fprintf(stderr, "Error: not implemented channel emulator\n");
|
||||
exit(-1);
|
||||
//break;
|
||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||
default:
|
||||
populate_channel_single(h[0][0]);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i, j;
|
||||
int i, j, k;
|
||||
float mse;
|
||||
cf_t *x[SRSLTE_MAX_LAYERS], *r[SRSLTE_MAX_PORTS], *y[SRSLTE_MAX_PORTS], *h[SRSLTE_MAX_PORTS],
|
||||
cf_t *x[SRSLTE_MAX_LAYERS], *r[SRSLTE_MAX_PORTS], *y[SRSLTE_MAX_PORTS], *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
*xr[SRSLTE_MAX_LAYERS];
|
||||
srslte_mimo_type_t type;
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
if (nof_ports > SRSLTE_MAX_PORTS || nof_layers > SRSLTE_MAX_LAYERS) {
|
||||
/* Check input ranges */
|
||||
if (nof_tx_ports > SRSLTE_MAX_PORTS || nof_rx_ports > SRSLTE_MAX_PORTS || nof_layers > SRSLTE_MAX_LAYERS) {
|
||||
fprintf(stderr, "Invalid number of layers or ports\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Parse MIMO Type */
|
||||
if (srslte_str2mimotype(mimo_type_name, &type)) {
|
||||
fprintf(stderr, "Invalid MIMO type %s\n", mimo_type_name);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Check scenario conditions are OK */
|
||||
switch (type) {
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
nof_re = nof_layers*nof_symbols;
|
||||
break;
|
||||
case SRSLTE_MIMO_TYPE_CDD:
|
||||
nof_re = nof_symbols*nof_tx_ports/nof_layers;
|
||||
if (nof_rx_ports != 2 || nof_tx_ports != 2) {
|
||||
fprintf(stderr, "CDD nof_tx_ports=%d nof_rx_ports=%d is not currently supported\n", nof_tx_ports, nof_rx_ports);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nof_re = nof_symbols*nof_layers;
|
||||
}
|
||||
|
||||
/* Allocate x and xr (received symbols) in memory for each layer */
|
||||
for (i = 0; i < nof_layers; i++) {
|
||||
/* Source data */
|
||||
x[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols);
|
||||
if (!x[i]) {
|
||||
perror("srslte_vec_malloc");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Sink data */
|
||||
xr[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols);
|
||||
if (!xr[i]) {
|
||||
perror("srslte_vec_malloc");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < nof_ports; i++) {
|
||||
y[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols * nof_layers);
|
||||
// TODO: The number of symbols per port is different in spatial multiplexing.
|
||||
|
||||
/* Allocate y in memory for tx each port */
|
||||
for (i = 0; i < nof_tx_ports; i++) {
|
||||
y[i] = srslte_vec_malloc(sizeof(cf_t) * nof_re);
|
||||
if (!y[i]) {
|
||||
perror("srslte_vec_malloc");
|
||||
exit(-1);
|
||||
}
|
||||
h[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols * nof_layers);
|
||||
if (!h[i]) {
|
||||
}
|
||||
|
||||
/* Allocate h in memory for each cross channel and layer */
|
||||
for (i = 0; i < nof_tx_ports; i++) {
|
||||
for (j = 0; j < nof_rx_ports; j++) {
|
||||
h[i][j] = srslte_vec_malloc(sizeof(cf_t) * nof_re);
|
||||
if (!h[i][j]) {
|
||||
perror("srslte_vec_malloc");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate r */
|
||||
for (i = 0; i < nof_rx_ports; i++) {
|
||||
r[i] = srslte_vec_malloc(sizeof(cf_t) * nof_re);
|
||||
if (!r[i]) {
|
||||
perror("srslte_vec_malloc");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* only 1 receiver antenna supported now */
|
||||
r[0] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols * nof_layers);
|
||||
if (!r[0]) {
|
||||
perror("srslte_vec_malloc");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* generate random data */
|
||||
/* Generate source random data */
|
||||
for (i = 0; i < nof_layers; i++) {
|
||||
for (j = 0; j < nof_symbols; j++) {
|
||||
x[i][j] = (2*(rand()%2)-1+(2*(rand()%2)-1)*_Complex_I)/sqrt(2);
|
||||
x[i][j] = (2 * (rand() % 2) - 1 + (2 * (rand() % 2) - 1) * _Complex_I) / sqrt(2);
|
||||
}
|
||||
}
|
||||
|
||||
/* precoding */
|
||||
if (srslte_precoding_type(x, y, nof_layers, nof_ports, nof_symbols, type) < 0) {
|
||||
|
||||
/* Execute Precoding (Tx) */
|
||||
if (srslte_precoding_type(x, y, nof_layers, nof_tx_ports, nof_symbols, type) < 0) {
|
||||
fprintf(stderr, "Error layer mapper encoder\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* generate channel */
|
||||
for (i = 0; i < nof_ports; i++) {
|
||||
for (j = 0; j < nof_symbols; j++) {
|
||||
h[i][nof_layers*j] = (float) rand()/RAND_MAX+((float) rand()/RAND_MAX)*_Complex_I;
|
||||
// assume the channel is time-invariant in nlayer consecutive symbols
|
||||
for (int k=0;k<nof_layers;k++) {
|
||||
h[i][nof_layers*j+k] = h[i][nof_layers*j];
|
||||
populate_channel(type, h);
|
||||
|
||||
/* pass signal through channel
|
||||
(we are in the frequency domain so it's a multiplication) */
|
||||
for (i = 0; i < nof_rx_ports; i++) {
|
||||
for (k = 0; k < nof_re; k++) {
|
||||
r[i][k] = (cf_t) (0.0 + 0.0 * _Complex_I);
|
||||
for (j = 0; j < nof_tx_ports; j++) {
|
||||
r[i][k] += y[j][k] * h[j][i][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* pass signal through channel
|
||||
(we are in the frequency domain so it's a multiplication) */
|
||||
/* there's only one receiver antenna, signals from different transmitter
|
||||
* ports are simply combined at the receiver
|
||||
*/
|
||||
for (j = 0; j < nof_symbols * nof_layers; j++) {
|
||||
r[0][j] = 0;
|
||||
for (i = 0; i < nof_ports; i++) {
|
||||
r[0][j] += y[i][j] * h[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
/* predecoding / equalization */
|
||||
struct timeval t[3];
|
||||
gettimeofday(&t[1], NULL);
|
||||
if (srslte_predecoding_type(r[0], h, xr, nof_ports, nof_layers,
|
||||
nof_symbols * nof_layers, type, 0) < 0) {
|
||||
fprintf(stderr, "Error layer mapper encoder\n");
|
||||
exit(-1);
|
||||
}
|
||||
srslte_predecoding_type_multi(r, h, xr, nof_rx_ports, nof_tx_ports, nof_layers,
|
||||
nof_re, type, 0);
|
||||
gettimeofday(&t[2], NULL);
|
||||
get_time_interval(t);
|
||||
printf("Execution Time: %ld us\n", t[0].tv_usec);
|
||||
|
@ -187,17 +263,22 @@ int main(int argc, char **argv) {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
/* Free all data */
|
||||
for (i = 0; i < nof_layers; i++) {
|
||||
free(x[i]);
|
||||
free(xr[i]);
|
||||
}
|
||||
for (i = 0; i < nof_ports; i++) {
|
||||
free(y[i]);
|
||||
free(h[i]);
|
||||
|
||||
for (i = 0; i < nof_rx_ports; i++) {
|
||||
free(r[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < nof_rx_ports; i++) {
|
||||
for (j = 0; j < nof_tx_ports; j++) {
|
||||
free(h[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(r[0]);
|
||||
|
||||
printf("Ok\n");
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -48,118 +48,159 @@ void help()
|
|||
/* the gateway function */
|
||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
const mwSize *dims = mxGetDimensions(INPUT);
|
||||
mwSize ndims;
|
||||
cf_t *input = NULL;
|
||||
cf_t *hest = NULL;
|
||||
cf_t *output = NULL;
|
||||
uint32_t nof_symbols = 0;
|
||||
uint32_t nof_rx_ants = 1;
|
||||
uint32_t nof_layers;
|
||||
uint32_t nof_tx_ports = 1;
|
||||
uint32_t nof_codewords = 1;
|
||||
float noise_estimate = 0;
|
||||
cf_t *x[SRSLTE_MAX_LAYERS];
|
||||
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
cf_t *y[SRSLTE_MAX_PORTS];
|
||||
int symbols_layers[SRSLTE_MAX_LAYERS];
|
||||
int i, j;
|
||||
srslte_mimo_type_t type;
|
||||
|
||||
/* Print help if number of inputs does not match with expected */
|
||||
if (nrhs < NOF_INPUTS) {
|
||||
help();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read input symbols
|
||||
/* Read input symbols */
|
||||
if (mexutils_read_cf(INPUT, &input) < 0) {
|
||||
mexErrMsgTxt("Error reading input\n");
|
||||
return;
|
||||
}
|
||||
uint32_t nof_layers = mxGetScalar(NLAYERS);
|
||||
uint32_t nof_tx_ports = 1;
|
||||
uint32_t nof_codewords = 1;
|
||||
|
||||
uint32_t nof_rx_ants = 1;
|
||||
const mwSize *dims = mxGetDimensions(INPUT);
|
||||
mwSize ndims = mxGetNumberOfDimensions(INPUT);
|
||||
nof_symbols = dims[0];
|
||||
|
||||
/* Read number of layers */
|
||||
nof_layers = (uint32_t) mxGetScalar(NLAYERS);
|
||||
|
||||
if (nof_layers > SRSLTE_MAX_LAYERS) {
|
||||
mexErrMsgTxt("Too many layers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read number of symbols and Rx antennas */
|
||||
ndims = mxGetNumberOfDimensions(INPUT);
|
||||
nof_symbols = (uint32_t) dims[0];
|
||||
|
||||
if (ndims >= 2) {
|
||||
nof_rx_ants = dims[1];
|
||||
nof_rx_ants = (uint32_t) dims[1];
|
||||
}
|
||||
|
||||
// Read channel estimates
|
||||
/* Read channel estimates */
|
||||
if (mexutils_read_cf(HEST, &hest) < 0) {
|
||||
mexErrMsgTxt("Error reading hest\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get number of tx ports */
|
||||
dims = mxGetDimensions(HEST);
|
||||
ndims = mxGetNumberOfDimensions(HEST);
|
||||
|
||||
if (ndims == 3) {
|
||||
nof_tx_ports = dims[2];
|
||||
nof_tx_ports = (uint32_t) dims[2];
|
||||
}
|
||||
|
||||
|
||||
/* Print parameters trace */
|
||||
mexPrintf("nof_tx_ports=%d, nof_rx_ants=%d, nof_layers=%d, nof_symbols=%d\n", nof_tx_ports, nof_rx_ants, nof_layers, nof_symbols);
|
||||
|
||||
// Read noise estimate
|
||||
float noise_estimate = 0;
|
||||
/* Read noise estimate */
|
||||
if (nrhs >= NOF_INPUTS) {
|
||||
noise_estimate = mxGetScalar(NEST);
|
||||
noise_estimate = (float) mxGetScalar(NEST);
|
||||
}
|
||||
|
||||
cf_t *x[SRSLTE_MAX_LAYERS];
|
||||
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
cf_t *y[SRSLTE_MAX_PORTS];
|
||||
|
||||
for (int i=0;i<SRSLTE_MAX_LAYERS;i++) {
|
||||
/* Initialise x, h & y pointers */
|
||||
for (i=0;i<SRSLTE_MAX_LAYERS;i++) {
|
||||
x[i] = NULL;
|
||||
}
|
||||
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
for (int j=0;j<SRSLTE_MAX_PORTS;j++) {
|
||||
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
for (j=0;j<SRSLTE_MAX_PORTS;j++) {
|
||||
h[i][j] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
output = srslte_vec_malloc(sizeof(cf_t)*nof_symbols);
|
||||
for (int i = 0; i < nof_tx_ports; i++) {
|
||||
x[i] = srslte_vec_malloc(sizeof(cf_t)*nof_symbols);
|
||||
for (int j=0;j<nof_rx_ants;j++) {
|
||||
h[i][j] = &hest[i*nof_symbols*nof_rx_ants + j*nof_symbols];
|
||||
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
y[i] = NULL;
|
||||
}
|
||||
|
||||
/* Allocate memory for ouput */
|
||||
output = srslte_vec_malloc(sizeof(cf_t)*nof_symbols*nof_layers);
|
||||
|
||||
/* Allocate memory for intermediate data */
|
||||
for (i = 0; i < nof_tx_ports; i++) {
|
||||
x[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols);
|
||||
}
|
||||
|
||||
/* Allocate memory for channel estimate */
|
||||
for (i = 0; i < nof_tx_ports; i++) {
|
||||
for (j=0; j<nof_rx_ants; j++) {
|
||||
h[i][j] = &hest[(i*nof_rx_ants + j)*nof_symbols];
|
||||
}
|
||||
}
|
||||
|
||||
for (int j=0;j<nof_rx_ants;j++) {
|
||||
|
||||
/* Allocate memory for input */
|
||||
for (j = 0; j < nof_rx_ants; j++) {
|
||||
y[j] = &input[j*nof_symbols];
|
||||
}
|
||||
|
||||
char *txscheme = "Port0";
|
||||
|
||||
/* Parse Tx scheme */
|
||||
char txscheme[32] = "Port0";
|
||||
if (nrhs >= NOF_INPUTS) {
|
||||
txscheme = mxArrayToString(TXSCHEME);
|
||||
}
|
||||
srslte_mimo_type_t type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||
mxGetString_700(TXSCHEME, txscheme, 32);
|
||||
}
|
||||
|
||||
if (!strcmp(txscheme, "Port0")) {
|
||||
type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||
} else if (!strcmp(txscheme, "TxDiversity")) {
|
||||
type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||
} else if (!strcmp(txscheme, "CDD")) {
|
||||
type = SRSLTE_MIMO_TYPE_CDD;
|
||||
} else if (!strcmp(txscheme, "SpatialMux")) {
|
||||
} else if (!strcmp(txscheme, "SpatialMux")) {
|
||||
type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||
} else {
|
||||
mexPrintf("Unsupported TxScheme=%s\n", txscheme);
|
||||
return;
|
||||
}
|
||||
int symbols_layers[SRSLTE_MAX_LAYERS];
|
||||
for (int i=0;i<nof_layers;i++) {
|
||||
|
||||
/* Populate symbols in layers */
|
||||
for (i = 0; i < nof_layers; i++) {
|
||||
symbols_layers[i] = nof_symbols;
|
||||
}
|
||||
cf_t *d[SRSLTE_MAX_LAYERS];
|
||||
d[0] = output;
|
||||
srslte_predecoding_type_multi(y, h, x, nof_rx_ants, nof_tx_ports, nof_layers, nof_symbols/nof_layers, type, noise_estimate);
|
||||
|
||||
/* Set output pointer */
|
||||
cf_t *d[SRSLTE_MAX_CODEWORDS];
|
||||
for (i = 0; i<nof_codewords; i++) {
|
||||
d[i] = output;
|
||||
}
|
||||
|
||||
/* Pre-decode */
|
||||
srslte_predecoding_type_multi(y, h, x, nof_rx_ants, nof_tx_ports, nof_layers, nof_symbols, type, noise_estimate);
|
||||
|
||||
/* Layer de-mapper */
|
||||
srslte_layerdemap_type(x, d, nof_layers, nof_codewords, nof_symbols, symbols_layers, type);
|
||||
|
||||
|
||||
if (nlhs >= 1) {
|
||||
mexutils_write_cf(output, &plhs[0], nof_symbols, 1);
|
||||
/* Write output */
|
||||
if (nlhs >= 1) {
|
||||
mexutils_write_cf(output, &plhs[0], nof_symbols*nof_layers*nof_rx_ants/nof_tx_ports, 1);
|
||||
}
|
||||
|
||||
|
||||
/* Free memory */
|
||||
if (input) {
|
||||
free(input);
|
||||
}
|
||||
if (hest) {
|
||||
free(hest);
|
||||
}
|
||||
if (output) {
|
||||
free(output);
|
||||
}
|
||||
for (int i=0;i<SRSLTE_MAX_LAYERS;i++) {
|
||||
for (i=0;i<SRSLTE_MAX_LAYERS;i++) {
|
||||
if (x[i]) {
|
||||
free(x[i]);
|
||||
}
|
||||
|
|
|
@ -1051,6 +1051,16 @@ int dci_format2AB_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t
|
|||
} else {
|
||||
*y++ = data->tb_cw_swap;
|
||||
}
|
||||
|
||||
/* Force MCS_idx and RV_idx in function of block enable according to 7.1.7 of 36.213 */
|
||||
if (!data->tb_en[0]) {
|
||||
data->mcs_idx = 0;
|
||||
data->rv_idx= 1;
|
||||
}
|
||||
if (!data->tb_en[1]) {
|
||||
data->mcs_idx_1 = 0;
|
||||
data->rv_idx_1 = 1;
|
||||
}
|
||||
|
||||
/* pack TB1 */
|
||||
srslte_bit_unpack(data->mcs_idx, &y, 5);
|
||||
|
|
|
@ -65,7 +65,19 @@ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell
|
|||
return srslte_pdcch_init_multi(q, regs, cell, 1);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas)
|
||||
int srslte_pdcch_init_tx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
|
||||
return srslte_pdcch_init_txrx(q, regs, cell, 1, false);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_rx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
|
||||
return srslte_pdcch_init_txrx(q, regs, cell, nof_rx_antennas, true);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
|
||||
return srslte_pdcch_init_txrx(q, regs, cell, nof_rx_antennas, true);
|
||||
}
|
||||
|
||||
int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas, bool isReceiver)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
|
@ -122,19 +134,25 @@ int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_
|
|||
goto clean;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->ce[i][j]) {
|
||||
goto clean;
|
||||
}
|
||||
if (isReceiver) {
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
for (int j = 0; j < q->nof_rx_antennas; j++) {
|
||||
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->ce[i][j]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->x[i]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
|
||||
for (int j = 0; j < ((isReceiver) ? q->nof_rx_antennas : cell.nof_ports); j++) {
|
||||
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
|
||||
if (!q->symbols[j]) {
|
||||
goto clean;
|
||||
|
|
|
@ -203,20 +203,15 @@ int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols,
|
|||
return srslte_pdsch_cp(q, sf_symbols, symbols, grant, lstart, subframe, false);
|
||||
}
|
||||
|
||||
int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell)
|
||||
{
|
||||
return srslte_pdsch_init_multi(q, cell, 1);
|
||||
}
|
||||
|
||||
/** Initializes the PDCCH transmitter and receiver */
|
||||
int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_rx_antennas)
|
||||
/** Initializes the PDCCH transmitter or receiver */
|
||||
int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antennas, bool is_receiver)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
int i;
|
||||
|
||||
if (q != NULL &&
|
||||
srslte_cell_isvalid(&cell) &&
|
||||
nof_rx_antennas <= SRSLTE_MAX_PORTS)
|
||||
nof_antennas <= SRSLTE_MAX_PORTS)
|
||||
{
|
||||
|
||||
bzero(q, sizeof(srslte_pdsch_t));
|
||||
|
@ -224,8 +219,10 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
|
|||
|
||||
q->cell = cell;
|
||||
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
|
||||
q->nof_rx_antennas = nof_rx_antennas;
|
||||
|
||||
if (is_receiver) {
|
||||
q->nof_rx_antennas = nof_antennas;
|
||||
}
|
||||
|
||||
INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
|
||||
q->cell.nof_prb, q->max_re);
|
||||
|
||||
|
@ -244,20 +241,37 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
|
|||
goto clean;
|
||||
}
|
||||
|
||||
q->e2 = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
|
||||
if (!q->e) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
q->d = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->d) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
q->d2 = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->d) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
/* Layer mapped symbols memory allocation */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->x[i]) {
|
||||
goto clean;
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->ce[i][j]) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
/* If it is the receiver side, allocate estimated channel */
|
||||
if (is_receiver) {
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
for (int j = 0; j < q->nof_rx_antennas; j++) {
|
||||
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
|
||||
if (!q->ce[i][j]) {
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -268,6 +282,7 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
|
|||
}
|
||||
}
|
||||
|
||||
/* Allocate User memory (all zeros) */
|
||||
q->users = calloc(sizeof(srslte_pdsch_user_t*), 1+SRSLTE_SIRNTI);
|
||||
if (!q->users) {
|
||||
perror("malloc");
|
||||
|
@ -283,15 +298,33 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
|
|||
return ret;
|
||||
}
|
||||
|
||||
int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) {
|
||||
return srslte_pdsch_init_multi(q, cell, 1, true);
|
||||
}
|
||||
|
||||
int srslte_pdsch_init_tx_multi(srslte_pdsch_t *q, srslte_cell_t cell) {
|
||||
return srslte_pdsch_init_multi(q, cell, 0, false);
|
||||
}
|
||||
|
||||
int srslte_pdsch_init_rx_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antennas) {
|
||||
return srslte_pdsch_init_multi(q, cell, nof_antennas, true);
|
||||
}
|
||||
|
||||
void srslte_pdsch_free(srslte_pdsch_t *q) {
|
||||
int i;
|
||||
|
||||
if (q->e) {
|
||||
free(q->e);
|
||||
}
|
||||
if (q->e2) {
|
||||
free(q->e2);
|
||||
}
|
||||
if (q->d) {
|
||||
free(q->d);
|
||||
}
|
||||
if (q->d2) {
|
||||
free(q->d2);
|
||||
}
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (q->x[i]) {
|
||||
free(q->x[i]);
|
||||
|
@ -302,7 +335,7 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
for (int j=0;j<SRSLTE_MAX_PORTS;j++) {
|
||||
if (q->symbols[j]) {
|
||||
free(q->symbols[j]);
|
||||
}
|
||||
|
@ -348,6 +381,50 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_g
|
|||
}
|
||||
}
|
||||
|
||||
/* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg.
|
||||
* If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
|
||||
*/
|
||||
int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi,
|
||||
uint32_t sf_idx, uint32_t rvidx, uint32_t rvidx2)
|
||||
{
|
||||
if (cfg) {
|
||||
if (grant) {
|
||||
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
|
||||
}
|
||||
if (srslte_cbsegm(&cfg->cb_segm, (uint32_t) cfg->grant.mcs.tbs)) {
|
||||
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs.tbs);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (srslte_cbsegm(&cfg->cb_segm2, (uint32_t) cfg->grant.mcs2.tbs)) {
|
||||
fprintf(stderr, "Error computing Codeblock (2) segmentation for TBS=%d\n", cfg->grant.mcs.tbs);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
srslte_ra_dl_grant_to_nbits_multi(&cfg->grant, cfi, cell, sf_idx, &cfg->nbits, &cfg->nbits2);
|
||||
cfg->sf_idx = sf_idx;
|
||||
cfg->rv = rvidx;
|
||||
cfg->rv2 = rvidx2;
|
||||
|
||||
if (cell.nof_ports == 1 && grant->nof_tb == 1) {
|
||||
cfg->mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||
cfg->nof_layers = 1;
|
||||
} else if (cell.nof_ports == 2 && grant->nof_tb == 1) {
|
||||
cfg->mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||
cfg->nof_layers = 2;
|
||||
} else if (cell.nof_ports == 2 && grant->nof_tb == 2) {
|
||||
cfg->mimo_type = SRSLTE_MIMO_TYPE_CDD;
|
||||
cfg->nof_layers = 2;
|
||||
} else {
|
||||
INFO("nof_ports=%d, nof_tb=%d are not consistent\n", cell.nof_ports, grant->nof_tb);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
|
||||
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
|
||||
|
@ -362,6 +439,10 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
|
|||
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (srslte_sequence_pdsch(&q->users[rnti]->seq2[i], rnti, 1, 2 * i, q->cell.id,
|
||||
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
q->users[rnti]->sequence_generated = true;
|
||||
}
|
||||
|
@ -374,6 +455,7 @@ void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti)
|
|||
if (q->users[rnti]) {
|
||||
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
srslte_sequence_free(&q->users[rnti]->seq[i]);
|
||||
srslte_sequence_free(&q->users[rnti]->seq2[i]);
|
||||
}
|
||||
free(q->users[rnti]);
|
||||
q->users[rnti] = NULL;
|
||||
|
@ -392,15 +474,15 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
|
|||
for (int i=0;i<q->cell.nof_ports;i++) {
|
||||
_ce[i][0] = ce[i];
|
||||
}
|
||||
return srslte_pdsch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, rnti, data);
|
||||
return srslte_pdsch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, rnti, &data);
|
||||
}
|
||||
|
||||
/** Decodes the PDSCH from the received symbols
|
||||
*/
|
||||
int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
|
||||
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
|
||||
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS],
|
||||
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)
|
||||
uint16_t rnti, uint8_t *data[SRSLTE_MAX_CODEWORDS])
|
||||
{
|
||||
|
||||
/* Set pointers for layermapping & precoding */
|
||||
|
@ -441,22 +523,38 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO: only diversity is supported */
|
||||
if (q->cell.nof_ports == 1) {
|
||||
/* no need for layer demapping */
|
||||
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits.nof_re, noise_estimate);
|
||||
} else {
|
||||
srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nbits.nof_re);
|
||||
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, cfg->nbits.nof_re / q->cell.nof_ports);
|
||||
int nof_symbols [SRSLTE_MAX_CODEWORDS];
|
||||
nof_symbols[0] = cfg->nbits.nof_re * cfg->grant.nof_tb / q->cell.nof_ports;
|
||||
nof_symbols[1] = cfg->nbits2.nof_re * cfg->grant.nof_tb / q->cell.nof_ports;
|
||||
|
||||
srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers,
|
||||
cfg->nbits.nof_re, cfg->mimo_type, 0.0);
|
||||
srslte_layerdemap_type(x, (cf_t *[SRSLTE_MAX_CODEWORDS]) {q->d, q->d2}, cfg->nof_layers, cfg->grant.nof_tb,
|
||||
nof_symbols[0], nof_symbols, cfg->mimo_type);
|
||||
}
|
||||
|
||||
if (SRSLTE_VERBOSE_ISDEBUG()) {
|
||||
DEBUG("SAVED FILE subframe.dat: received subframe symbols\n",0);
|
||||
srslte_vec_save_file("subframe.dat", sf_symbols[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
DEBUG("SAVED FILE hest0.dat and hest1.dat: channel estimates for port 0 and port 1\n",0);
|
||||
srslte_vec_save_file("hest0.dat", ce[0][0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
if (q->cell.nof_ports > 1) {
|
||||
srslte_vec_save_file("hest1.dat", ce[1][0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
char filename[FILENAME_MAX];
|
||||
for (int j = 0; j < q->nof_rx_antennas; j++) {
|
||||
if (snprintf(filename, FILENAME_MAX, "subframe_p%d.dat", j) < 0) {
|
||||
ERROR("Generating file name");
|
||||
break;
|
||||
}
|
||||
DEBUG("SAVED FILE %s: received subframe symbols\n", filename);
|
||||
srslte_vec_save_file(filename, sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (snprintf(filename, FILENAME_MAX, "hest_%d%d.dat", i, j) < 0) {
|
||||
ERROR("Generating file name");
|
||||
break;
|
||||
}
|
||||
DEBUG("SAVED FILE %s: channel estimates for Tx %d and Rx %d\n", filename, j, i);
|
||||
srslte_vec_save_file(filename, ce[i][j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||||
}
|
||||
}
|
||||
DEBUG("SAVED FILE pdsch_symbols.dat: symbols after equalization\n",0);
|
||||
srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits.nof_re*sizeof(cf_t));
|
||||
|
@ -466,18 +564,40 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
|
|||
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
|
||||
* thus we don't need tot set it in the LLRs normalization
|
||||
*/
|
||||
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
|
||||
|
||||
if (cfg->nbits.nof_re) {
|
||||
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
|
||||
}
|
||||
|
||||
if (cfg->nbits2.nof_re) {
|
||||
srslte_demod_soft_demodulate_s(cfg->grant.mcs2.mod, q->d2, q->e2, cfg->nbits2.nof_re);
|
||||
}
|
||||
|
||||
/* descramble */
|
||||
if (q->users[rnti] && q->users[rnti]->sequence_generated) {
|
||||
srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits);
|
||||
if (cfg->nbits.nof_bits) {
|
||||
srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits);
|
||||
}
|
||||
|
||||
if (cfg->nbits2.nof_bits) {
|
||||
srslte_scrambling_s_offset(&q->users[rnti]->seq2[cfg->sf_idx], q->e2, 0, cfg->nbits2.nof_bits);
|
||||
}
|
||||
} else {
|
||||
srslte_sequence_t seq;
|
||||
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
|
||||
return SRSLTE_ERROR;
|
||||
if (cfg->nbits.nof_bits) {
|
||||
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits);
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
|
||||
if (cfg->nbits2.nof_bits) {
|
||||
if (srslte_sequence_pdsch(&seq, rnti, 1, 2 * cfg->sf_idx, q->cell.id, cfg->nbits2.nof_bits)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_scrambling_s_offset(&seq, q->e2, 0, cfg->nbits2.nof_bits);
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits);
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
|
||||
if (SRSLTE_VERBOSE_ISDEBUG()) {
|
||||
|
@ -485,7 +605,8 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
|
|||
srslte_vec_save_file("llr.dat", q->e, cfg->nbits.nof_bits*sizeof(int16_t));
|
||||
}
|
||||
|
||||
return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data);
|
||||
return srslte_dlsch_decode_multi(&q->dl_sch, cfg, softbuffers, (int16_t *[SRSLTE_MAX_CODEWORDS]) {q->e, q->e2},
|
||||
data);
|
||||
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
@ -571,6 +692,112 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int srslte_pdsch_encode_multi(srslte_pdsch_t *q,
|
||||
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]) {
|
||||
|
||||
int i;
|
||||
/* Set pointers for layermapping & precoding */
|
||||
cf_t *x[SRSLTE_MAX_LAYERS];
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
cfg != NULL) {
|
||||
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (sf_symbols[i] == NULL) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
/* If both transport block sizes are zero return error */
|
||||
if (cfg->grant.mcs.tbs == 0 && cfg->grant.mcs2.tbs == 0) {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
if (cfg->nbits.nof_re > q->max_re) {
|
||||
fprintf(stderr,
|
||||
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n",
|
||||
cfg->nbits.nof_re, q->max_re, q->cell.nof_prb);
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
INFO("Encoding PDSCH SF: %d (TB 1), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
|
||||
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs,
|
||||
cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv);
|
||||
if (cfg->grant.nof_tb > 1) {
|
||||
INFO("Encoding PDSCH SF: %d (TB 2), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
|
||||
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs2.mod), cfg->grant.mcs2.tbs,
|
||||
cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv2);
|
||||
}
|
||||
|
||||
/* number of layers equals number of ports */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
x[i] = q->x[i];
|
||||
}
|
||||
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
|
||||
|
||||
if (srslte_dlsch_encode_multi(&q->dl_sch, cfg, softbuffers, data, (uint8_t *[SRSLTE_MAX_CODEWORDS]) {q->e, q->e2})) {
|
||||
fprintf(stderr, "Error encoding TB\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
/* scramble */
|
||||
if (!q->users[rnti]) {
|
||||
srslte_sequence_t seq;
|
||||
|
||||
if (cfg->nbits.nof_bits) {
|
||||
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_scrambling_bytes(&seq, (uint8_t *) q->e, cfg->nbits.nof_bits);
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
|
||||
if (cfg->nbits2.nof_bits) {
|
||||
if (srslte_sequence_pdsch(&seq, rnti, 1, 2 * cfg->sf_idx, q->cell.id, cfg->nbits2.nof_bits)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_scrambling_bytes(&seq, (uint8_t *) q->e2, cfg->nbits2.nof_bits);
|
||||
srslte_sequence_free(&seq);
|
||||
}
|
||||
} else {
|
||||
if (cfg->nbits.nof_bits) {
|
||||
srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t *) q->e, cfg->nbits.nof_bits);
|
||||
}
|
||||
|
||||
if (cfg->nbits2.nof_bits) {
|
||||
srslte_scrambling_bytes(&q->users[rnti]->seq2[cfg->sf_idx], (uint8_t *) q->e2, cfg->nbits2.nof_bits);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->nbits.nof_bits) {
|
||||
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t *) q->e, q->d, cfg->nbits.nof_bits);
|
||||
}
|
||||
|
||||
if (cfg->nbits2.nof_bits) {
|
||||
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs2.mod], (uint8_t *) q->e2, q->d2, cfg->nbits2.nof_bits);
|
||||
}
|
||||
|
||||
if (q->cell.nof_ports > 1) {
|
||||
int nof_symbols = srslte_layermap_type((cf_t *[SRSLTE_MAX_CODEWORDS]) {q->d, q->d2}, x, cfg->grant.nof_tb, cfg->nof_layers,
|
||||
(int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits.nof_re, cfg->nbits2.nof_re}, cfg->mimo_type);
|
||||
srslte_precoding_type(x, q->symbols, q->cell.nof_ports, cfg->nof_layers,
|
||||
nof_symbols, cfg->mimo_type);
|
||||
} else {
|
||||
memcpy(q->symbols[0], q->d, cfg->nbits.nof_re * sizeof(cf_t));
|
||||
}
|
||||
|
||||
/* mapping to resource elements */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx);
|
||||
}
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
float srslte_pdsch_average_noi(srslte_pdsch_t *q)
|
||||
{
|
||||
return q->dl_sch.average_nof_iterations;
|
||||
|
|
|
@ -826,4 +826,4 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -496,7 +496,6 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
|
|||
grant->mcs.tbs = (uint32_t) tbs;
|
||||
} else {
|
||||
n_prb = grant->nof_prb;
|
||||
grant->nof_tb = 0;
|
||||
if (dci->tb_en[0]) {
|
||||
grant->mcs.idx = dci->mcs_idx;
|
||||
tbs = dl_fill_ra_mcs(&grant->mcs, n_prb);
|
||||
|
@ -506,7 +505,6 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
|
|||
// For mcs>=29, set last TBS received for this PID
|
||||
grant->mcs.tbs = last_dl_tbs[dci->harq_process%8];
|
||||
}
|
||||
grant->nof_tb++;
|
||||
} else {
|
||||
grant->mcs.tbs = 0;
|
||||
}
|
||||
|
@ -519,16 +517,18 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
|
|||
// For mcs>=29, set last TBS received for this PID
|
||||
grant->mcs2.tbs = last_dl_tbs2[dci->harq_process%8];
|
||||
}
|
||||
grant->nof_tb++;
|
||||
} else {
|
||||
grant->mcs2.tbs = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
grant->nof_tb = 0;
|
||||
if (dci->tb_en[0]) {
|
||||
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
|
||||
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
|
||||
grant->nof_tb++;
|
||||
}
|
||||
if (dci->tb_en[1]) {
|
||||
grant->Qm2 = srslte_mod_bits_x_symbol(grant->mcs2.mod);
|
||||
grant->Qm2 = srslte_mod_bits_x_symbol(grant->mcs2.mod);
|
||||
grant->nof_tb++;
|
||||
}
|
||||
if (tbs < 0) {
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -546,6 +546,23 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl
|
|||
nbits->nof_bits = nbits->nof_re * grant->Qm;
|
||||
}
|
||||
|
||||
void srslte_ra_dl_grant_to_nbits_multi(srslte_ra_dl_grant_t *grant, uint32_t cfi, srslte_cell_t cell, uint32_t sf_idx,
|
||||
srslte_ra_nbits_t *nbits, srslte_ra_nbits_t *nbits2) {
|
||||
/* Compute number of RE for first transport block */
|
||||
nbits->nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb<10?(cfi+1):cfi);
|
||||
nbits->lstart = cell.nof_prb<10?(cfi+1):cfi;
|
||||
nbits->nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-nbits->lstart;
|
||||
nbits->nof_bits = nbits->nof_re * grant->Qm;
|
||||
|
||||
/*/ Compute number of RE for second transport block */
|
||||
if (grant->nof_tb > 1) {
|
||||
nbits2->nof_re = nbits->nof_re;
|
||||
nbits2->lstart = nbits->lstart;
|
||||
nbits2->nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits2->lstart;
|
||||
nbits2->nof_bits = nbits2->nof_re * grant->Qm2;
|
||||
}
|
||||
}
|
||||
|
||||
/** Obtains a DL grant from a DCI grant for PDSCH */
|
||||
int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
|
||||
uint32_t nof_prb, uint16_t msg_rnti, srslte_ra_dl_grant_t *grant)
|
||||
|
@ -796,18 +813,31 @@ void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_dl_dci_t *dci, uint32_t nof_prb)
|
|||
}
|
||||
break;
|
||||
}
|
||||
fprintf(f, " - Modulation and coding scheme index:\t%d\n", dci->mcs_idx);
|
||||
fprintf(f, " - HARQ process:\t\t\t%d\n", dci->harq_process);
|
||||
fprintf(f, " - New data indicator:\t\t\t%s\n", dci->ndi ? "Yes" : "No");
|
||||
fprintf(f, " - Redundancy version:\t\t\t%d\n", dci->rv_idx);
|
||||
fprintf(f, " - TPC command for PUCCH:\t\t--\n");
|
||||
fprintf(f, " - Transport blocks swapped:\t\t%s\n", (dci->tb_cw_swap)?"true":"false");
|
||||
fprintf(f, " - Transport block 1 enabled:\t\t%s\n", (dci->tb_en[0])?"true":"false");
|
||||
if (dci->tb_en[0]) {
|
||||
fprintf(f, " + Modulation and coding scheme index:\t%d\n", dci->mcs_idx);
|
||||
fprintf(f, " + New data indicator:\t\t\t%s\n", dci->ndi ? "Yes" : "No");
|
||||
fprintf(f, " + Redundancy version:\t\t\t%d\n", dci->rv_idx);
|
||||
}
|
||||
fprintf(f, " - Transport block 2 enabled:\t\t%s\n", (dci->tb_en[1])?"true":"false");
|
||||
if (dci->tb_en[1]) {
|
||||
fprintf(f, " + Modulation and coding scheme index:\t%d\n", dci->mcs_idx_1);
|
||||
fprintf(f, " + New data indicator:\t\t\t%s\n", dci->ndi_1 ? "Yes" : "No");
|
||||
fprintf(f, " + Redundancy version:\t\t\t%d\n", dci->rv_idx_1);
|
||||
}
|
||||
}
|
||||
|
||||
void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
|
||||
srslte_ra_prb_fprint(f, grant);
|
||||
fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb);
|
||||
fprintf(f, " - Number of TBs:\t\t\t%d\n", grant->nof_tb);
|
||||
fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs.mod));
|
||||
fprintf(f, " - Transport block size:\t\t%d\n", grant->mcs.tbs);
|
||||
fprintf(f, " - Modulation type (TB2):\t\t%s\n", srslte_mod_string(grant->mcs2.mod));
|
||||
fprintf(f, " - Transport block size (TB2):\t\t%d\n", grant->mcs2.tbs);
|
||||
}
|
||||
|
||||
void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
|
||||
|
|
|
@ -523,6 +523,32 @@ int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf
|
|||
e_bits, data);
|
||||
}
|
||||
|
||||
|
||||
int srslte_dlsch_decode_multi(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS],
|
||||
int16_t *e_bits[SRSLTE_MAX_CODEWORDS], uint8_t *data[SRSLTE_MAX_CODEWORDS])
|
||||
{
|
||||
int ret = SRSLTE_SUCCESS;
|
||||
uint32_t Nl = 1;
|
||||
|
||||
if (cfg->nof_layers != cfg->grant.nof_tb) {
|
||||
Nl = 2;
|
||||
}
|
||||
|
||||
if (cfg->nbits.nof_bits) {
|
||||
ret |= decode_tb(q, &softbuffers[0], &cfg->cb_segm,
|
||||
cfg->grant.Qm*Nl, cfg->rv, cfg->nbits.nof_bits,
|
||||
e_bits[0], data[0]);
|
||||
}
|
||||
|
||||
if (cfg->nbits2.nof_bits) {
|
||||
ret |= decode_tb(q, &softbuffers[1], &cfg->cb_segm2,
|
||||
cfg->grant.Qm2*Nl, cfg->rv2, cfg->nbits2.nof_bits,
|
||||
e_bits[1], data[1]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode transport block. Segments into code blocks, adds channel coding, and does rate matching.
|
||||
*
|
||||
|
@ -542,6 +568,35 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf
|
|||
data, e_bits);
|
||||
}
|
||||
|
||||
int srslte_dlsch_encode_multi(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS],
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS], uint8_t *e_bits[SRSLTE_MAX_CODEWORDS])
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t Nl = 1;
|
||||
|
||||
if (cfg->nof_layers != cfg->grant.nof_tb) {
|
||||
Nl = 2;
|
||||
}
|
||||
|
||||
/* Check if codeword 1 shall be encoded */
|
||||
if(cfg->nbits.nof_bits) {
|
||||
ret |= encode_tb(q,
|
||||
&softbuffers[0], &cfg->cb_segm,
|
||||
cfg->grant.Qm*Nl, cfg->rv, cfg->nbits.nof_bits,
|
||||
data[0], e_bits[0]);
|
||||
}
|
||||
|
||||
/* Check if codeword 2 shall be encoded */
|
||||
if(cfg->nbits2.nof_bits) {
|
||||
ret |= encode_tb(q,
|
||||
&softbuffers[1], &cfg->cb_segm2,
|
||||
cfg->grant.Qm2*Nl, cfg->rv2, cfg->nbits2.nof_bits,
|
||||
data[1], e_bits[1]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Compute the interleaving function on-the-fly, because it depends on number of RI bits
|
||||
* Profiling show that the computation of this matrix is neglegible.
|
||||
*/
|
||||
|
|
|
@ -87,6 +87,27 @@ add_test(pdsch_test_qam16 pdsch_test -m 20 -n 100)
|
|||
add_test(pdsch_test_qam16 pdsch_test -m 20 -n 100 -r 2)
|
||||
add_test(pdsch_test_qam64 pdsch_test -m 28 -n 100)
|
||||
|
||||
add_test(pdsch_test_sin_6 pdsch_test -p 1 -a 2 -w 1 -n 6)
|
||||
add_test(pdsch_test_sin_12 pdsch_test -p 1 -a 2 -w 1 -n 12)
|
||||
add_test(pdsch_test_sin_25 pdsch_test -p 1 -a 2 -w 1 -n 25)
|
||||
add_test(pdsch_test_sin_50 pdsch_test -p 1 -a 2 -w 1 -n 50)
|
||||
add_test(pdsch_test_sin_75 pdsch_test -p 1 -a 2 -w 1 -n 75)
|
||||
add_test(pdsch_test_sin_100 pdsch_test -p 1 -a 2 -w 1 -n 100 -m 28)
|
||||
|
||||
add_test(pdsch_test_div_6 pdsch_test -p 2 -a 2 -w 1 -n 6)
|
||||
add_test(pdsch_test_div_12 pdsch_test -p 2 -a 2 -w 1 -n 12)
|
||||
add_test(pdsch_test_div_25 pdsch_test -p 2 -a 2 -w 1 -n 25)
|
||||
add_test(pdsch_test_div_50 pdsch_test -p 2 -a 2 -w 1 -n 50)
|
||||
add_test(pdsch_test_div_75 pdsch_test -p 2 -a 2 -w 1 -n 75)
|
||||
add_test(pdsch_test_div_100 pdsch_test -p 2 -a 2 -w 1 -n 100 -m 28)
|
||||
|
||||
add_test(pdsch_test_cdd_6 pdsch_test -p 2 -a 2 -w 2 -n 6)
|
||||
add_test(pdsch_test_cdd_12 pdsch_test -p 2 -a 2 -w 2 -n 12)
|
||||
add_test(pdsch_test_cdd_25 pdsch_test -p 2 -a 2 -w 2 -n 25)
|
||||
add_test(pdsch_test_cdd_50 pdsch_test -p 2 -a 2 -w 2 -n 50)
|
||||
add_test(pdsch_test_cdd_75 pdsch_test -p 2 -a 2 -w 2 -n 75)
|
||||
add_test(pdsch_test_cdd_100 pdsch_test -p 2 -a 2 -w 2 -n 100 -m 28 -M 28)
|
||||
|
||||
########################################################################
|
||||
# FILE TEST
|
||||
########################################################################
|
||||
|
|
|
@ -43,9 +43,14 @@ void help()
|
|||
/* the gateway function */
|
||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
int i;
|
||||
srslte_sch_t dlsch;
|
||||
srslte_pdsch_cfg_t cfg;
|
||||
srslte_softbuffer_tx_t softbuffer;
|
||||
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
|
||||
uint32_t nof_codewords = 1;
|
||||
|
||||
memset(&dlsch, 0, sizeof(srslte_sch_t));
|
||||
memset(&cfg, 0, sizeof(srslte_pdsch_cfg_t));
|
||||
|
||||
if (nrhs < NOF_INPUTS) {
|
||||
help();
|
||||
|
@ -62,6 +67,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
srslte_verbose = SRSLTE_VERBOSE_NONE;
|
||||
|
||||
uint8_t *trblkin_bits = NULL;
|
||||
cfg.grant.nof_tb = 1;
|
||||
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin_bits);
|
||||
if (cfg.grant.mcs.tbs == 0) {
|
||||
mexErrMsgTxt("Error trblklen is zero\n");
|
||||
|
@ -76,6 +82,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
return;
|
||||
}
|
||||
|
||||
if (mexutils_read_uint32_struct(PUSCHCFG, "NLayers", &cfg.nof_layers)) {
|
||||
mexErrMsgTxt("Field NLayers not found in dlsch config\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
|
||||
|
||||
if (!strcmp(mod_str, "QPSK")) {
|
||||
|
@ -94,9 +105,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
mxFree(mod_str);
|
||||
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
|
||||
mexErrMsgTxt("Error initiating DL-SCH soft buffer\n");
|
||||
return;
|
||||
/* Initialise buffers */
|
||||
for (i = 0; i < nof_codewords; i++) {
|
||||
softbuffers[i] = srslte_vec_malloc(sizeof(srslte_softbuffer_tx_t));
|
||||
if (srslte_softbuffer_tx_init(softbuffers[i], cell.nof_prb)) {
|
||||
mexErrMsgTxt("Error initiating DL-SCH soft buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cfg.nbits.nof_bits = mxGetScalar(OUTLEN);
|
||||
|
@ -111,13 +126,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
uint32_t tmp_rv=cfg.rv;
|
||||
if (tmp_rv) {
|
||||
cfg.rv = 0;
|
||||
if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) {
|
||||
if (srslte_dlsch_encode_multi(&dlsch, &cfg, softbuffers, &trblkin, &e_bits)) {
|
||||
mexErrMsgTxt("Error encoding TB\n");
|
||||
return;
|
||||
}
|
||||
cfg.rv = tmp_rv;
|
||||
}
|
||||
if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) {
|
||||
if (srslte_dlsch_encode_multi(&dlsch, &cfg, softbuffers, &trblkin, &e_bits)) {
|
||||
mexErrMsgTxt("Error encoding TB\n");
|
||||
return;
|
||||
}
|
||||
|
@ -135,7 +150,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
free(trblkin);
|
||||
free(e_bits);
|
||||
free(e_bits_unpacked);
|
||||
|
||||
for (i = 0; i < nof_codewords; i++) {
|
||||
srslte_softbuffer_tx_free(softbuffers[i]);
|
||||
free(softbuffers[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,22 +27,26 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <srslte/phy/common/phy_common.h>
|
||||
#include <srslte/phy/phch/ra.h>
|
||||
#include <srslte/phy/phch/dci.h>
|
||||
#include <srslte/phy/phch/pdcch.h>
|
||||
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
srslte_cell_t cell = {
|
||||
6, // nof_prb
|
||||
1, // nof_ports
|
||||
1, // cell_id
|
||||
SRSLTE_CP_NORM, // cyclic prefix
|
||||
SRSLTE_PHICH_R_1, // PHICH resources
|
||||
SRSLTE_PHICH_NORM // PHICH length
|
||||
.nof_prb = 6,
|
||||
.nof_ports = 1,
|
||||
.id = 1,
|
||||
.cp = SRSLTE_CP_NORM,
|
||||
.phich_resources = SRSLTE_PHICH_R_1,
|
||||
.phich_length = SRSLTE_PHICH_NORM
|
||||
};
|
||||
|
||||
uint32_t cfi = 1;
|
||||
bool print_dci_table;
|
||||
uint32_t nof_rx_ant = 1;
|
||||
bool print_dci_table;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [cfpndv]\n", prog);
|
||||
|
@ -50,25 +54,29 @@ void usage(char *prog) {
|
|||
printf("\t-f cfi [Default %d]\n", cfi);
|
||||
printf("\t-p cell.nof_ports [Default %d]\n", cell.nof_ports);
|
||||
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
|
||||
printf("\t-A nof_rx_ant [Default %d]\n", nof_rx_ant);
|
||||
printf("\t-d Print DCI table [Default %s]\n", print_dci_table?"yes":"no");
|
||||
printf("\t-v [set srslte_verbose to debug, default none]\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "cfpndv")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "cfpndvA")) != -1) {
|
||||
switch (opt) {
|
||||
case 'p':
|
||||
cell.nof_ports = atoi(argv[optind]);
|
||||
cell.nof_ports = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'f':
|
||||
cfi = atoi(argv[optind]);
|
||||
cfi = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'n':
|
||||
cell.nof_prb = atoi(argv[optind]);
|
||||
cell.nof_prb = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'c':
|
||||
cell.id = atoi(argv[optind]);
|
||||
cell.id = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'A':
|
||||
nof_rx_ant = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'd':
|
||||
print_dci_table = true;
|
||||
|
@ -85,25 +93,26 @@ void parse_args(int argc, char **argv) {
|
|||
|
||||
int test_dci_payload_size() {
|
||||
int i, j;
|
||||
int x[4];
|
||||
const srslte_dci_format_t formats[4] = { SRSLTE_DCI_FORMAT0, SRSLTE_DCI_FORMAT1, SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1C };
|
||||
int x[5];
|
||||
const srslte_dci_format_t formats[] = { SRSLTE_DCI_FORMAT0, SRSLTE_DCI_FORMAT1, SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1C, SRSLTE_DCI_FORMAT2A };
|
||||
const int prb[6] = { 6, 15, 25, 50, 75, 100 };
|
||||
const int dci_sz[6][5] = { { 21, 19, 21, 8 }, { 22, 23, 22, 10 }, { 25, 27,
|
||||
25, 12 }, { 27, 31, 27, 13 }, { 27, 33, 27, 14 }, { 28, 39, 28, 15 } };
|
||||
const int dci_sz[6][5] = { { 21, 19, 21, 8, 28 }, { 22, 23, 22, 10 , 31}, { 25, 27,
|
||||
25, 12 , 36}, { 27, 31, 27, 13 , 41}, { 27, 33, 27, 14 , 42}, { 28, 39, 28, 15, 48 }};
|
||||
|
||||
|
||||
printf("Testing DCI payload sizes...\n");
|
||||
printf(" PRB\t0\t1\t1A\t1C\n");
|
||||
printf(" PRB\t0\t1\t1A\t1C\t2A\n");
|
||||
for (i = 0; i < 6; i++) {
|
||||
int n = prb[i];
|
||||
for (j = 0; j < 4; j++) {
|
||||
x[j] = srslte_dci_format_sizeof(formats[j], n, 1);
|
||||
for (j = 0; j < 5; j++) {
|
||||
x[j] = srslte_dci_format_sizeof(formats[j], (uint32_t) n, 1);
|
||||
if (x[j] != dci_sz[i][j]) {
|
||||
fprintf(stderr, "Invalid DCI payload size for %s\n",
|
||||
srslte_dci_format_string(formats[j]));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
printf(" %2d:\t%2d\t%2d\t%2d\t%2d\n", n, x[0], x[1], x[2], x[3]);
|
||||
printf(" %2d:\t%2d\t%2d\t%2d\t%2d\t%2d\n", n, x[0], x[1], x[2], x[3], x[4]);
|
||||
}
|
||||
printf("Ok\n");
|
||||
|
||||
|
@ -111,8 +120,8 @@ int test_dci_payload_size() {
|
|||
printf("dci_sz_table[101][4] = {\n");
|
||||
for (i=0;i<=100;i++) {
|
||||
printf(" {");
|
||||
for (int j=0;j<4;j++) {
|
||||
printf("%d",srslte_dci_format_sizeof(formats[j], i, 1));
|
||||
for (j=0;j<4;j++) {
|
||||
printf("%d",srslte_dci_format_sizeof(formats[j], (uint32_t) i, 1));
|
||||
if (j<3) {
|
||||
printf(", ");
|
||||
}
|
||||
|
@ -128,16 +137,23 @@ int test_dci_payload_size() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
srslte_dci_msg_t dci_tx, dci_rx;
|
||||
srslte_dci_location_t dci_location;
|
||||
srslte_dci_format_t dci_format;
|
||||
srslte_ra_dl_dci_t ra_dl_tx;
|
||||
srslte_ra_dl_dci_t ra_dl_rx;
|
||||
} testcase_dci_t;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
srslte_pdcch_t pdcch;
|
||||
srslte_dci_msg_t dci_tx[2], dci_rx[2], dci_tmp;
|
||||
srslte_dci_location_t dci_locations[2];
|
||||
srslte_pdcch_t pdcch_tx, pdcch_rx;
|
||||
testcase_dci_t testcases[10] = {0};
|
||||
srslte_ra_dl_dci_t ra_dl;
|
||||
srslte_regs_t regs;
|
||||
int i, j;
|
||||
cf_t *ce[SRSLTE_MAX_PORTS];
|
||||
int i, j, k;
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
int nof_re;
|
||||
cf_t *slot_symbols[SRSLTE_MAX_PORTS];
|
||||
cf_t *tx_slot_symbols[SRSLTE_MAX_PORTS], *rx_slot_symbols[SRSLTE_MAX_PORTS];
|
||||
int nof_dcis;
|
||||
|
||||
int ret = -1;
|
||||
|
@ -152,19 +168,30 @@ int main(int argc, char **argv) {
|
|||
|
||||
/* init memory */
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
ce[i] = malloc(sizeof(cf_t) * nof_re);
|
||||
if (!ce[i]) {
|
||||
for (j = 0; j < SRSLTE_MAX_PORTS; j++) {
|
||||
ce[i][j] = malloc(sizeof(cf_t) * nof_re);
|
||||
if (!ce[i][j]) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
}
|
||||
for (k = 0; k < nof_re; k++) {
|
||||
//ce[i][j][k] = (i == j) ? 1 : 0;
|
||||
ce[i][j][k] = ((float)rand()/(float)RAND_MAX) + _Complex_I*((float)rand()/(float)RAND_MAX);
|
||||
}
|
||||
}
|
||||
tx_slot_symbols[i] = malloc(sizeof(cf_t) * nof_re);
|
||||
if (!tx_slot_symbols[i]) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
}
|
||||
for (j = 0; j < nof_re; j++) {
|
||||
ce[i][j] = 1;
|
||||
}
|
||||
slot_symbols[i] = malloc(sizeof(cf_t) * nof_re);
|
||||
if (!slot_symbols[i]) {
|
||||
bzero(tx_slot_symbols[i], sizeof(cf_t) * nof_re);
|
||||
|
||||
rx_slot_symbols[i] = malloc(sizeof(cf_t) * nof_re);
|
||||
if (!rx_slot_symbols[i]) {
|
||||
perror("malloc");
|
||||
exit(-1);
|
||||
}
|
||||
bzero(rx_slot_symbols[i], sizeof(cf_t) * nof_re);
|
||||
}
|
||||
|
||||
if (srslte_regs_init(®s, cell)) {
|
||||
|
@ -177,12 +204,18 @@ int main(int argc, char **argv) {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
if (srslte_pdcch_init(&pdcch, ®s, cell)) {
|
||||
if (srslte_pdcch_init_tx(&pdcch_tx, ®s, cell)) {
|
||||
fprintf(stderr, "Error creating PDCCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
nof_dcis = 2;
|
||||
if (srslte_pdcch_init_rx(&pdcch_rx, ®s, cell, nof_rx_ant)) {
|
||||
fprintf(stderr, "Error creating PDCCH object\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Resource allocate init */
|
||||
nof_dcis = 0;
|
||||
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
|
||||
ra_dl.harq_process = 0;
|
||||
ra_dl.mcs_idx = 5;
|
||||
|
@ -190,62 +223,131 @@ int main(int argc, char **argv) {
|
|||
ra_dl.rv_idx = 0;
|
||||
ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
|
||||
ra_dl.type0_alloc.rbg_bitmask = 0x5;
|
||||
ra_dl.tb_en[0] = true;
|
||||
|
||||
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_tx[0], cell.nof_prb, cell.nof_ports, false);
|
||||
srslte_dci_location_set(&dci_locations[0], 0, 0);
|
||||
/* Format 1 Test case */
|
||||
testcases[nof_dcis].dci_format = SRSLTE_DCI_FORMAT1;
|
||||
testcases[nof_dcis].ra_dl_tx = ra_dl;
|
||||
nof_dcis++;
|
||||
|
||||
/* Format 1 Test case */
|
||||
ra_dl.mcs_idx = 15;
|
||||
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_tx[1], cell.nof_prb, cell.nof_ports, false);
|
||||
srslte_dci_location_set(&dci_locations[1], 0, 1);
|
||||
|
||||
testcases[nof_dcis].dci_format = SRSLTE_DCI_FORMAT1;
|
||||
testcases[nof_dcis].ra_dl_tx = ra_dl;
|
||||
nof_dcis++;
|
||||
|
||||
/* Tx Diversity Test case */
|
||||
if (cell.nof_ports > 1) {
|
||||
ra_dl.mcs_idx_1 = 0;
|
||||
ra_dl.rv_idx_1 = 0;
|
||||
ra_dl.ndi_1 = false;
|
||||
ra_dl.tb_en[1] = false;
|
||||
testcases[nof_dcis].dci_format = SRSLTE_DCI_FORMAT2A;
|
||||
testcases[nof_dcis].ra_dl_tx = ra_dl;
|
||||
nof_dcis++;
|
||||
}
|
||||
|
||||
/* CDD Spatial Multiplexing Test case */
|
||||
if (cell.nof_ports > 1) {
|
||||
ra_dl.mcs_idx_1 = 28;
|
||||
ra_dl.rv_idx_1 = 1;
|
||||
ra_dl.ndi_1 = false;
|
||||
ra_dl.tb_en[1] = true;
|
||||
testcases[nof_dcis].dci_format = SRSLTE_DCI_FORMAT2A;
|
||||
testcases[nof_dcis].ra_dl_tx = ra_dl;
|
||||
nof_dcis++;
|
||||
}
|
||||
|
||||
/* Execute Rx */
|
||||
for (i=0;i<nof_dcis;i++) {
|
||||
if (srslte_pdcch_encode(&pdcch, &dci_tx[i], dci_locations[i], 1234+i, slot_symbols, 0, cfi)) {
|
||||
srslte_dci_msg_pack_pdsch(&testcases[i].ra_dl_tx, testcases[i].dci_format, &testcases[i].dci_tx,
|
||||
cell.nof_prb, cell.nof_ports, false);
|
||||
srslte_dci_location_set(&testcases[i].dci_location, 0, (uint32_t) i);
|
||||
|
||||
if (srslte_pdcch_encode(&pdcch_tx, &testcases[i].dci_tx, testcases[i].dci_location, (uint16_t) (1234 + i),
|
||||
tx_slot_symbols, 0, cfi)) {
|
||||
fprintf(stderr, "Error encoding DCI message\n");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
srslte_vec_fprint_b(stdout, dci_tx[0].data, dci_tx[0].nof_bits);
|
||||
/* combine outputs */
|
||||
for (i = 1; i < cell.nof_ports; i++) {
|
||||
for (j = 0; j < nof_re; j++) {
|
||||
slot_symbols[0][j] += slot_symbols[i][j];
|
||||
/* Apply channel */
|
||||
for (j = 0; j < nof_rx_ant; j++) {
|
||||
for (k = 0; k < nof_re; k++) {
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
rx_slot_symbols[j][k] += tx_slot_symbols[i][k]*ce[i][j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<2;i++) {
|
||||
if (srslte_pdcch_extract_llr(&pdcch, slot_symbols[0], ce, 0, 0, cfi)) {
|
||||
fprintf(stderr, "Error extracting LLRs\n");
|
||||
goto quit;
|
||||
}
|
||||
uint16_t crc_rem;
|
||||
if (srslte_pdcch_decode_msg(&pdcch, &dci_tmp, &dci_locations[i], SRSLTE_DCI_FORMAT1, &crc_rem)) {
|
||||
/* Execute 'Rx' */
|
||||
if (srslte_pdcch_extract_llr_multi(&pdcch_rx, rx_slot_symbols, ce, 0, 0, cfi)) {
|
||||
fprintf(stderr, "Error extracting LLRs\n");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* Decode DCIs */
|
||||
for (i=0;i<nof_dcis;i++) {
|
||||
uint16_t crc_rem;
|
||||
if (srslte_pdcch_decode_msg(&pdcch_rx, &testcases[i].dci_rx, &testcases[i].dci_location, testcases[i].dci_format, &crc_rem)) {
|
||||
fprintf(stderr, "Error decoding DCI message\n");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
if (srslte_dci_msg_unpack_pdsch(&testcases[i].dci_rx, &testcases[i].ra_dl_rx, cell.nof_prb, cell.nof_ports, false)) {
|
||||
fprintf(stderr, "Error unpacking DCI message\n");
|
||||
goto quit;
|
||||
}
|
||||
if (crc_rem >= 1234 && crc_rem < 1234 + nof_dcis) {
|
||||
crc_rem -= 1234;
|
||||
memcpy(&dci_rx[crc_rem], &dci_tmp, sizeof(srslte_dci_msg_t));
|
||||
} else {
|
||||
printf("Received invalid DCI CRC 0x%x\n", crc_rem);
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare Tx and Rx */
|
||||
for (i = 0; i < nof_dcis; i++) {
|
||||
if (memcmp(dci_tx[i].data, dci_rx[i].data, dci_tx[i].nof_bits)) {
|
||||
if (memcmp(testcases[i].dci_tx.data, testcases[i].dci_rx.data, testcases[i].dci_tx.nof_bits)) {
|
||||
printf("Error in DCI %d: Received data does not match\n", i);
|
||||
goto quit;
|
||||
}
|
||||
if (memcmp(&testcases[i].ra_dl_tx, &testcases[i].ra_dl_rx, sizeof(srslte_ra_dl_dci_t))) {
|
||||
printf("Error in RA %d: Received data does not match\n", i);
|
||||
printf(" Field | Tx | Rx \n");
|
||||
printf("--------------+----------+----------\n");
|
||||
printf(" harq_process | %8d | %8d\n", testcases[i].ra_dl_tx.harq_process, testcases[i].ra_dl_rx.harq_process);
|
||||
printf(" mcs_idx | %8d | %8d\n", testcases[i].ra_dl_tx.mcs_idx, testcases[i].ra_dl_rx.mcs_idx);
|
||||
printf(" rv_idx | %8d | %8d\n", testcases[i].ra_dl_tx.rv_idx, testcases[i].ra_dl_rx.rv_idx);
|
||||
printf(" ndi | %8d | %8d\n", testcases[i].ra_dl_tx.ndi, testcases[i].ra_dl_rx.ndi);
|
||||
printf(" mcs_idx_1 | %8d | %8d\n", testcases[i].ra_dl_tx.mcs_idx_1, testcases[i].ra_dl_rx.mcs_idx_1);
|
||||
printf(" rv_idx_1 | %8d | %8d\n", testcases[i].ra_dl_tx.rv_idx_1, testcases[i].ra_dl_rx.rv_idx_1);
|
||||
printf(" ndi_1 | %8d | %8d\n", testcases[i].ra_dl_tx.ndi_1, testcases[i].ra_dl_rx.ndi_1);
|
||||
printf(" tb_cw_swap | %8d | %8d\n", testcases[i].ra_dl_tx.tb_cw_swap, testcases[i].ra_dl_rx.tb_cw_swap);
|
||||
printf(" sram_id | %8d | %8d\n", testcases[i].ra_dl_tx.sram_id, testcases[i].ra_dl_rx.sram_id);
|
||||
printf(" pinfo | %8d | %8d\n", testcases[i].ra_dl_tx.pinfo, testcases[i].ra_dl_rx.pinfo);
|
||||
printf(" pconf | %8d | %8d\n", testcases[i].ra_dl_tx.pconf, testcases[i].ra_dl_rx.pconf);
|
||||
printf(" power_offset | %8d | %8d\n", testcases[i].ra_dl_tx.power_offset, testcases[i].ra_dl_rx.power_offset);
|
||||
printf(" tpc_pucch | %8d | %8d\n", testcases[i].ra_dl_tx.tpc_pucch, testcases[i].ra_dl_rx.tpc_pucch);
|
||||
printf(" tb_en[0] | %8d | %8d\n", testcases[i].ra_dl_tx.tb_en[0], testcases[i].ra_dl_rx.tb_en[0]);
|
||||
printf(" tb_en[1] | %8d | %8d\n", testcases[i].ra_dl_tx.tb_en[1], testcases[i].ra_dl_rx.tb_en[1]);
|
||||
printf(" dci_is_1a | %8d | %8d\n", testcases[i].ra_dl_tx.dci_is_1a, testcases[i].ra_dl_rx.dci_is_1a);
|
||||
printf(" dci_is_1c | %8d | %8d\n", testcases[i].ra_dl_tx.dci_is_1c, testcases[i].ra_dl_rx.dci_is_1c);
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
quit:
|
||||
srslte_pdcch_free(&pdcch);
|
||||
srslte_pdcch_free(&pdcch_tx);
|
||||
srslte_pdcch_free(&pdcch_rx);
|
||||
srslte_regs_free(®s);
|
||||
|
||||
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
|
||||
free(ce[i]);
|
||||
free(slot_symbols[i]);
|
||||
for (j = 0; j < SRSLTE_MAX_PORTS; j++) {
|
||||
free(ce[i][j]);
|
||||
}
|
||||
free(tx_slot_symbols[i]);
|
||||
free(rx_slot_symbols[i]);
|
||||
}
|
||||
if (ret) {
|
||||
printf("Error\n");
|
||||
|
|
|
@ -33,13 +33,14 @@
|
|||
|
||||
#define ENBCFG prhs[0]
|
||||
#define RNTI prhs[1]
|
||||
#define INPUT prhs[2]
|
||||
#define NOF_INPUTS 3
|
||||
#define AMP prhs[2]
|
||||
#define INPUT prhs[3]
|
||||
#define NOF_INPUTS 4
|
||||
|
||||
|
||||
|
||||
srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also
|
||||
const uint32_t nof_ue_formats = 2;
|
||||
srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1,SRSLTE_DCI_FORMAT2B}; // SRSLTE_DCI_FORMAT1B should go here also
|
||||
const uint32_t nof_ue_formats = 3;
|
||||
|
||||
srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1C};
|
||||
const uint32_t nof_common_formats = 2;
|
||||
|
@ -162,7 +163,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
} else {
|
||||
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
|
||||
}
|
||||
mexPrintf("noise power=%f, RNTI=0x%x, cfi=%d\n", noise_power, rnti, cfi);
|
||||
|
||||
float amplitude = mxGetScalar(AMP);
|
||||
|
||||
srslte_viterbi_set_gain_quant(&pdcch.decoder, amplitude);
|
||||
|
||||
srslte_pdcch_extract_llr(&pdcch, input_fft, ce, noise_power, sf_idx, cfi);
|
||||
|
||||
|
|
|
@ -30,45 +30,60 @@
|
|||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <srslte/phy/phch/ra.h>
|
||||
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
// Enable to measure execution time
|
||||
//#define DO_OFDM
|
||||
|
||||
#ifdef DO_OFDM
|
||||
#define NOF_CE_SYMBOLS SRSLTE_SF_LEN_PRB(cell.nof_prb)
|
||||
#else
|
||||
#define NOF_CE_SYMBOLS SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)
|
||||
#endif
|
||||
|
||||
srslte_cell_t cell = {
|
||||
6, // nof_prb
|
||||
1, // nof_ports
|
||||
0, // cell_id
|
||||
SRSLTE_CP_NORM, // cyclic prefix
|
||||
SRSLTE_PHICH_R_1_6, // PHICH resources
|
||||
SRSLTE_PHICH_NORM // PHICH length
|
||||
SRSLTE_PHICH_NORM, // PHICH length
|
||||
SRSLTE_PHICH_R_1_6 // PHICH resources
|
||||
};
|
||||
|
||||
uint32_t cfi = 2;
|
||||
uint32_t mcs = 0;
|
||||
uint32_t mcs2 = 0;
|
||||
uint32_t subframe = 1;
|
||||
uint32_t rv_idx = 0;
|
||||
uint16_t rnti = 1234;
|
||||
uint32_t rv_idx2 = 0;
|
||||
uint16_t rnti = 1234;
|
||||
uint32_t nof_tb = 1;
|
||||
uint32_t nof_rx_antennas = 1;
|
||||
char *input_file = NULL;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [fmcsrRFpnv] \n", prog);
|
||||
printf("Usage: %s [fmMcsrtRFpnwav] \n", prog);
|
||||
printf("\t-f read signal from file [Default generate it with pdsch_encode()]\n");
|
||||
printf("\t-m MCS [Default %d]\n", mcs);
|
||||
printf("\t-M MCS2 [Default %d]\n", mcs2);
|
||||
printf("\t-c cell id [Default %d]\n", cell.id);
|
||||
printf("\t-s subframe [Default %d]\n", subframe);
|
||||
printf("\t-r rv_idx [Default %d]\n", rv_idx);
|
||||
printf("\t-t rv_idx2 [Default %d]\n", rv_idx2);
|
||||
printf("\t-R rnti [Default %d]\n", rnti);
|
||||
printf("\t-F cfi [Default %d]\n", cfi);
|
||||
printf("\t-p cell.nof_ports [Default %d]\n", cell.nof_ports);
|
||||
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
|
||||
printf("\t-w nof_tb [Default %d]\n", nof_tb);
|
||||
printf("\t-a nof_rx_antennas [Default %d]\n", nof_rx_antennas);
|
||||
printf("\t-v [set srslte_verbose to debug, default none]\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "fmcsrRFpnv")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "fmMcsrtRFpnwav")) != -1) {
|
||||
switch(opt) {
|
||||
case 'f':
|
||||
input_file = argv[optind];
|
||||
|
@ -76,12 +91,18 @@ void parse_args(int argc, char **argv) {
|
|||
case 'm':
|
||||
mcs = atoi(argv[optind]);
|
||||
break;
|
||||
case 'M':
|
||||
mcs2 = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 's':
|
||||
subframe = atoi(argv[optind]);
|
||||
break;
|
||||
case 'r':
|
||||
rv_idx = atoi(argv[optind]);
|
||||
break;
|
||||
case 't':
|
||||
rv_idx2 = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'R':
|
||||
rnti = atoi(argv[optind]);
|
||||
break;
|
||||
|
@ -97,6 +118,12 @@ void parse_args(int argc, char **argv) {
|
|||
case 'c':
|
||||
cell.id = atoi(argv[optind]);
|
||||
break;
|
||||
case 'w':
|
||||
nof_tb = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'a':
|
||||
nof_rx_antennas = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'v':
|
||||
srslte_verbose++;
|
||||
break;
|
||||
|
@ -107,30 +134,37 @@ void parse_args(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t *data = NULL;
|
||||
cf_t *ce[SRSLTE_MAX_PORTS];
|
||||
srslte_softbuffer_rx_t softbuffer_rx;
|
||||
uint8_t *data[SRSLTE_MAX_CODEWORDS] = {NULL};
|
||||
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
srslte_softbuffer_rx_t softbuffers_rx[SRSLTE_MAX_CODEWORDS];
|
||||
srslte_ra_dl_grant_t grant;
|
||||
srslte_pdsch_cfg_t pdsch_cfg;
|
||||
cf_t *sf_symbols;
|
||||
cf_t *slot_symbols[SRSLTE_MAX_PORTS];
|
||||
srslte_pdsch_t pdsch;
|
||||
#ifdef DO_OFDM
|
||||
cf_t *tx_sf_symbols[SRSLTE_MAX_PORTS];
|
||||
cf_t *rx_sf_symbols[SRSLTE_MAX_PORTS];
|
||||
#endif /* DO_OFDM */
|
||||
cf_t *tx_slot_symbols[SRSLTE_MAX_PORTS];
|
||||
cf_t *rx_slot_symbols[SRSLTE_MAX_PORTS];
|
||||
srslte_pdsch_t pdsch_tx, pdsch_rx;
|
||||
srslte_ofdm_t ofdm_tx, ofdm_rx;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
uint32_t i, j;
|
||||
uint32_t i, j, k;
|
||||
int ret = -1;
|
||||
struct timeval t[3];
|
||||
srslte_softbuffer_tx_t softbuffer_tx;
|
||||
srslte_softbuffer_tx_t softbuffers_tx[SRSLTE_MAX_CODEWORDS];
|
||||
|
||||
parse_args(argc,argv);
|
||||
|
||||
bzero(&pdsch, sizeof(srslte_pdsch_t));
|
||||
/* Initialise to zeros */
|
||||
bzero(&pdsch_tx, sizeof(srslte_pdsch_t));
|
||||
bzero(&pdsch_rx, sizeof(srslte_pdsch_t));
|
||||
bzero(&pdsch_cfg, sizeof(srslte_pdsch_cfg_t));
|
||||
bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
|
||||
bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
|
||||
bzero(&softbuffer_rx, sizeof(srslte_softbuffer_rx_t));
|
||||
bzero(&softbuffer_tx, sizeof(srslte_softbuffer_tx_t));
|
||||
bzero(tx_slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
|
||||
bzero(rx_slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
|
||||
bzero(softbuffers_tx, sizeof(srslte_softbuffer_tx_t)*SRSLTE_MAX_CODEWORDS);
|
||||
bzero(softbuffers_rx, sizeof(srslte_softbuffer_rx_t)*SRSLTE_MAX_CODEWORDS);
|
||||
|
||||
srslte_ra_dl_dci_t dci;
|
||||
bzero(&dci, sizeof(srslte_ra_dl_dci_t));
|
||||
|
@ -138,57 +172,136 @@ int main(int argc, char **argv) {
|
|||
dci.rv_idx = rv_idx;
|
||||
dci.type0_alloc.rbg_bitmask = 0xffffffff;
|
||||
dci.tb_en[0] = true;
|
||||
if (nof_tb > 1) {
|
||||
dci.mcs_idx_1 = mcs2;
|
||||
dci.rv_idx_1 = rv_idx2;
|
||||
dci.tb_en[1] = true;
|
||||
}
|
||||
|
||||
/* Generate grant from DCI */
|
||||
if (srslte_ra_dl_dci_to_grant(&dci, cell.nof_prb, rnti, &grant)) {
|
||||
fprintf(stderr, "Error computing resource allocation\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DO_OFDM
|
||||
srslte_ofdm_tx_init(&ofdm_tx, cell.cp, cell.nof_prb);
|
||||
srslte_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb);
|
||||
|
||||
sf_symbols=srslte_vec_malloc(sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
|
||||
srslte_ofdm_set_normalize(&ofdm_tx, true);
|
||||
srslte_ofdm_set_normalize(&ofdm_rx, true);
|
||||
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
}
|
||||
|
||||
for (i = 0; i < nof_rx_antennas; i++) {
|
||||
rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
}
|
||||
#endif /* DO_OFDM */
|
||||
|
||||
/* Configure PDSCH */
|
||||
if (srslte_pdsch_cfg(&pdsch_cfg, cell, &grant, cfi, subframe, rv_idx)) {
|
||||
if (srslte_pdsch_cfg_multi(&pdsch_cfg, cell, &grant, cfi, subframe, rv_idx, rv_idx2)) {
|
||||
fprintf(stderr, "Error configuring PDSCH\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Select MIMO mode */
|
||||
if (cell.nof_ports == 1 && nof_tb == 1) {
|
||||
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||
pdsch_cfg.nof_layers = 1;
|
||||
} else if (cell.nof_ports == 2 && nof_tb == 1) {
|
||||
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||
pdsch_cfg.nof_layers = 2;
|
||||
} else if (cell.nof_ports == 2 && nof_tb == 2) {
|
||||
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_CDD;
|
||||
pdsch_cfg.nof_layers = 2;
|
||||
} else {
|
||||
fprintf(stderr, "nof_ports=%d, nof_tb=%d are not consistent\n", cell.nof_ports, nof_tb);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* init memory */
|
||||
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
ce[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
||||
if (!ce[i]) {
|
||||
for (j = 0; j < SRSLTE_MAX_PORTS; j++) {
|
||||
ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * NOF_CE_SYMBOLS);
|
||||
if (!ce[i]) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto quit;
|
||||
}
|
||||
for (k = 0; k < NOF_CE_SYMBOLS; k++) {
|
||||
ce[i][j][k] = (i == j) ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
rx_slot_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
||||
if (!rx_slot_symbols[i]) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto quit;
|
||||
}
|
||||
for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
||||
ce[i][j] = 1;
|
||||
}
|
||||
slot_symbols[i] = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
||||
if (!slot_symbols[i]) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
data = srslte_vec_malloc(sizeof(uint8_t) * (grant.mcs.tbs/8)+24);
|
||||
if (!data) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (srslte_pdsch_init(&pdsch, cell)) {
|
||||
|
||||
if (grant.mcs.tbs) {
|
||||
data[0] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs);
|
||||
if (!data[0]) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
if (grant.mcs2.tbs) {
|
||||
data[1] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs);
|
||||
if (!data[1]) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
if (srslte_pdsch_init_rx_multi(&pdsch_rx, cell, nof_rx_antennas)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
srslte_pdsch_set_rnti(&pdsch, rnti);
|
||||
|
||||
if (srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating RX soft buffer\n");
|
||||
goto quit;
|
||||
|
||||
srslte_pdsch_set_rnti(&pdsch_rx, rnti);
|
||||
|
||||
for (i = 0; i < nof_tb; i++) {
|
||||
if (srslte_softbuffer_rx_init(&softbuffers_rx[i], cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating RX soft buffer\n");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
INFO(" nof_prb=%d\n", cell.nof_prb);
|
||||
INFO(" nof_ports=%d\n", cell.nof_ports);
|
||||
INFO(" id=%d\n", cell.id);
|
||||
INFO(" cp=%s\n", srslte_cp_string(cell.cp));
|
||||
INFO(" phich_length=%d\n", (int) cell.phich_length);
|
||||
INFO(" phich_resources=%d\n", (int) cell.phich_resources);
|
||||
INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb);
|
||||
INFO(" nof_prb=%d\n", pdsch_cfg.grant.nof_prb);
|
||||
INFO(" Qm=%d\n", pdsch_cfg.grant.Qm);
|
||||
INFO(" Qm2=%d\n", pdsch_cfg.grant.Qm2);
|
||||
INFO(" mcs.idx=0x%X\n", pdsch_cfg.grant.mcs.idx);
|
||||
INFO(" mcs.tbs=%d\n", pdsch_cfg.grant.mcs.tbs);
|
||||
INFO(" mcs.mod=%s\n", srslte_mod_string(pdsch_cfg.grant.mcs.mod));
|
||||
INFO(" mcs2.idx=0x%X\n", pdsch_cfg.grant.mcs2.idx);
|
||||
INFO(" mcs2.tbs=%d\n", pdsch_cfg.grant.mcs2.tbs);
|
||||
INFO(" mcs2.mod=%s\n", srslte_mod_string(pdsch_cfg.grant.mcs2.mod));
|
||||
INFO(" nof_layers=%d\n", pdsch_cfg.nof_layers);
|
||||
INFO(" rv=%d\n", pdsch_cfg.rv);
|
||||
INFO(" rv2=%d\n", pdsch_cfg.rv2);
|
||||
INFO(" sf_idx=%d\n", pdsch_cfg.sf_idx);
|
||||
INFO(" mimo_type=%d\n", (int) pdsch_cfg.mimo_type);
|
||||
INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb);
|
||||
INFO(" lstart=%d\n", pdsch_cfg.nbits.lstart);
|
||||
INFO(" nof_bits=%d\n", pdsch_cfg.nbits.nof_bits);
|
||||
INFO(" nof_re=%d\n", pdsch_cfg.nbits.nof_re);
|
||||
INFO(" nof_symb=%d\n", pdsch_cfg.nbits.nof_symb);
|
||||
INFO(" lstart=%d\n", pdsch_cfg.nbits2.lstart);
|
||||
INFO(" nof_bits=%d\n", pdsch_cfg.nbits2.nof_bits);
|
||||
INFO(" nof_re=%d\n", pdsch_cfg.nbits2.nof_re);
|
||||
INFO(" nof_symb=%d\n", pdsch_cfg.nbits2.nof_symb);
|
||||
|
||||
if (input_file) {
|
||||
srslte_filesource_t fsrc;
|
||||
if (srslte_filesource_init(&fsrc, input_file, SRSLTE_COMPLEX_FLOAT_BIN)) {
|
||||
|
@ -196,102 +309,156 @@ int main(int argc, char **argv) {
|
|||
exit(-1);
|
||||
}
|
||||
#ifdef DO_OFDM
|
||||
srslte_filesource_read(&fsrc, sf_symbols, SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
srslte_filesource_read(&fsrc, rx_slot_symbols, SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
#else
|
||||
srslte_filesource_read(&fsrc, slot_symbols[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
||||
srslte_filesource_read(&fsrc, rx_slot_symbols[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
||||
#endif
|
||||
|
||||
srslte_chest_dl_t chest;
|
||||
if (srslte_chest_dl_init(&chest, cell)) {
|
||||
printf("Error initializing equalizer\n");
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
exit(-1);
|
||||
}
|
||||
srslte_chest_dl_estimate(&chest, slot_symbols[0], ce, subframe);
|
||||
srslte_chest_dl_estimate(&chest, rx_slot_symbols[0], ce[0], subframe);
|
||||
srslte_chest_dl_free(&chest);
|
||||
|
||||
srslte_filesource_free(&fsrc);
|
||||
} else {
|
||||
if (srslte_softbuffer_tx_init(&softbuffer_tx, cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating TX soft buffer\n");
|
||||
} else {
|
||||
|
||||
if (srslte_pdsch_init_tx_multi(&pdsch_tx, cell)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
for (i=0;i<grant.mcs.tbs/8;i++) {
|
||||
data[i] = rand()%256;
|
||||
}
|
||||
|
||||
uint8_t databit[100000];
|
||||
srslte_bit_unpack_vector(data, databit, grant.mcs.tbs);
|
||||
srslte_vec_save_file("data_in", databit, grant.mcs.tbs);
|
||||
|
||||
if (!input_file) {
|
||||
|
||||
if (rv_idx) {
|
||||
/* Do 1st transmission for rv_idx!=0 */
|
||||
pdsch_cfg.rv = 0;
|
||||
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, rnti, slot_symbols)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
goto quit;
|
||||
}
|
||||
srslte_pdsch_set_rnti(&pdsch_tx, rnti);
|
||||
|
||||
for (i = 0; i < nof_tb; i++) {
|
||||
if (srslte_softbuffer_tx_init(&softbuffers_tx[i], cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating TX soft buffer\n");
|
||||
goto quit;
|
||||
}
|
||||
pdsch_cfg.rv = rv_idx;
|
||||
|
||||
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, rnti, slot_symbols)) {
|
||||
}
|
||||
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
tx_slot_symbols[i] = calloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), sizeof(cf_t));
|
||||
if (!tx_slot_symbols[i]) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < grant.mcs.tbs / 8; i++) {
|
||||
data[0][i] = (uint8_t) (rand() % 256);
|
||||
}
|
||||
|
||||
for (i = 0; i < grant.mcs2.tbs / 8; i++) {
|
||||
data[1][i] = (uint8_t) (rand() % 256);
|
||||
}
|
||||
|
||||
/*uint8_t databit[100000];
|
||||
srslte_bit_unpack_vector(data, databit, grant.mcs.tbs);
|
||||
srslte_vec_save_file("data_in", databit, grant.mcs.tbs);*/
|
||||
|
||||
if (rv_idx) {
|
||||
/* Do 1st transmission for rv_idx!=0 */
|
||||
pdsch_cfg.rv = 0;
|
||||
pdsch_cfg.rv2 = 0;
|
||||
if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
pdsch_cfg.rv = rv_idx;
|
||||
pdsch_cfg.rv2 = rv_idx2;
|
||||
if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
#ifdef DO_OFDM
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
/* For each Tx antenna modulate OFDM */
|
||||
srslte_ofdm_tx_sf(&ofdm_tx, tx_slot_symbols[i], tx_sf_symbols[i]);
|
||||
}
|
||||
|
||||
/* combine outputs */
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
||||
if (i > 0) {
|
||||
slot_symbols[0][j] += slot_symbols[i][j];
|
||||
for (j = 0; j < nof_rx_antennas; j++) {
|
||||
for (k = 0; k < NOF_CE_SYMBOLS; k++) {
|
||||
rx_sf_symbols[j][k] = 0.0f;
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
rx_sf_symbols[j][k] += tx_sf_symbols[i][k] * ce[i][j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* combine outputs */
|
||||
for (j = 0; j < nof_rx_antennas; j++) {
|
||||
for (k = 0; k < SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); k++) {
|
||||
rx_slot_symbols[j][k] = 0.0f;
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
rx_slot_symbols[j][k] += tx_slot_symbols[i][k] * ce[i][j][k];
|
||||
}
|
||||
ce[i][j] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DO_OFDM
|
||||
srslte_ofdm_tx_sf(&ofdm_tx, slot_symbols[0], sf_symbols);
|
||||
#endif
|
||||
}
|
||||
int M=1;
|
||||
|
||||
|
||||
}
|
||||
int M=10;
|
||||
int r=0;
|
||||
srslte_sch_set_max_noi(&pdsch.dl_sch, 10);
|
||||
srslte_sch_set_max_noi(&pdsch_rx.dl_sch, 10);
|
||||
gettimeofday(&t[1], NULL);
|
||||
for (i=0;i<M;i++) {
|
||||
#ifdef DO_OFDM
|
||||
srslte_ofdm_rx_sf(&ofdm_rx, sf_symbols, slot_symbols[1]);
|
||||
#endif
|
||||
srslte_softbuffer_rx_reset_tbs(&softbuffer_rx, grant.mcs.tbs);
|
||||
r = srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, rnti, data);
|
||||
for (k = 0; k < M; k++) {
|
||||
#ifdef DO_OFDM
|
||||
/* For each Rx antenna demodulate OFDM */
|
||||
for (i = 0; i < nof_rx_antennas; i++) {
|
||||
srslte_ofdm_rx_sf(&ofdm_rx, tx_sf_symbols[i], rx_slot_symbols[i]);
|
||||
}
|
||||
#endif
|
||||
if (grant.mcs.tbs) {
|
||||
srslte_softbuffer_rx_reset_tbs(&softbuffers_rx[0], (uint32_t) grant.mcs.tbs);
|
||||
}
|
||||
if (grant.mcs2.tbs) {
|
||||
srslte_softbuffer_rx_reset_tbs(&softbuffers_rx[1], (uint32_t) grant.mcs2.tbs);
|
||||
}
|
||||
r = srslte_pdsch_decode_multi(&pdsch_rx, &pdsch_cfg, softbuffers_rx, rx_slot_symbols, ce, 0, rnti, data);
|
||||
}
|
||||
gettimeofday(&t[2], NULL);
|
||||
get_time_interval(t);
|
||||
printf("DECODED %s in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", r?"Error":"OK",
|
||||
(float) t[0].tv_usec/M, (float) grant.mcs.tbs/1000, (float) grant.mcs.tbs*M/t[0].tv_usec);
|
||||
INFO("DECODED %s in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", r?"Error":"OK",
|
||||
(float) t[0].tv_usec/M, (float) (grant.mcs.tbs + grant.mcs2.tbs)/1000.0f,
|
||||
(float) (grant.mcs.tbs + grant.mcs2.tbs)*M/t[0].tv_usec);
|
||||
if (r) {
|
||||
ret = -1;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
quit:
|
||||
srslte_pdsch_free(&pdsch);
|
||||
srslte_softbuffer_tx_free(&softbuffer_tx);
|
||||
srslte_softbuffer_rx_free(&softbuffer_rx);
|
||||
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
if (ce[i]) {
|
||||
free(ce[i]);
|
||||
}
|
||||
if (slot_symbols[i]) {
|
||||
free(slot_symbols[i]);
|
||||
srslte_pdsch_free(&pdsch_tx);
|
||||
srslte_pdsch_free(&pdsch_rx);
|
||||
for (i = 0; i < nof_tb; i++) {
|
||||
srslte_softbuffer_tx_free(&softbuffers_tx[i]);
|
||||
srslte_softbuffer_rx_free(&softbuffers_rx[i]);
|
||||
|
||||
if (data[i]) {
|
||||
free(data[i]);
|
||||
}
|
||||
}
|
||||
if (data) {
|
||||
free(data);
|
||||
|
||||
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
for (j = 0; j < SRSLTE_MAX_PORTS; j++) {
|
||||
if (ce[i][j]) {
|
||||
free(ce[i][j]);
|
||||
}
|
||||
}
|
||||
if (tx_slot_symbols[i]) {
|
||||
free(tx_slot_symbols[i]);
|
||||
}
|
||||
if (rx_slot_symbols[i]) {
|
||||
free(rx_slot_symbols[i]);
|
||||
}
|
||||
}
|
||||
if (ret) {
|
||||
printf("Error\n");
|
||||
|
|
|
@ -101,7 +101,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
nof_antennas = dims[2];
|
||||
}
|
||||
|
||||
if (srslte_pdsch_init_multi(&pdsch, cell, nof_antennas)) {
|
||||
if (srslte_pdsch_init_rx_multi(&pdsch, cell, nof_antennas)) {
|
||||
mexErrMsgTxt("Error initiating PDSCH\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
srslte_prach_set_detect_factor(&prach, factor);
|
||||
}
|
||||
|
||||
mexPrintf("format=%d config=%d, N_cp=%d, ifft=%d\n", prach.f, prach.config_idx, prach.N_cp, prach.N_ifft_ul);
|
||||
|
||||
if (srslte_prach_detect_offset(&prach, frequency_offset, &input_signal[prach.N_cp], nof_samples, preambles, offsets, NULL, &nof_detected)) {
|
||||
mexErrMsgTxt("Error detecting PRACH\n");
|
||||
return;
|
||||
|
|
|
@ -172,7 +172,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
srslte_pucch_set_cfg(&pucch, &pucch_cfg, group_hopping_en);
|
||||
|
||||
if (srslte_pucch_encode(&pucch, format, n_pucch, sf_idx, bits, sf_symbols)) {
|
||||
if (srslte_pucch_encode(&pucch, format, n_pucch, sf_idx, (uint16_t) rnti, bits, sf_symbols)) {
|
||||
mexErrMsgTxt("Error encoding PUCCH\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -187,12 +187,14 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
srslte_pucch_set_cfg(&pucch, &pucch_cfg, group_hopping_en);
|
||||
|
||||
if (srslte_chest_ul_estimate_pucch(&chest_ul, sf_symbols, ce, format, n_pucch, sf_idx)) {
|
||||
uint8_t pucch2_ack_bits[2] = {0};
|
||||
|
||||
if (srslte_chest_ul_estimate_pucch(&chest_ul, sf_symbols, ce, format, n_pucch, sf_idx, &pucch2_ack_bits)) {
|
||||
mexErrMsgTxt("Error estimating PUCCH DMRS\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (srslte_pucch_decode(&pucch, format, n_pucch, sf_idx, sf_symbols, ce, 0, bits)<0) {
|
||||
if (srslte_pucch_decode(&pucch, format, n_pucch, sf_idx, (uint16_t) rnti, sf_symbols, ce, 0, bits)<0) {
|
||||
mexErrMsgTxt("Error decoding PUCCH\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ float rf_blade_get_rssi(void *h)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int rf_blade_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
|
||||
int rf_blade_open_multi(char *args, void **h, uint32_t nof_tx_antennas, uint32_t nof_rx_antennas)
|
||||
{
|
||||
return rf_blade_open(args, h);
|
||||
}
|
||||
|
@ -469,6 +469,20 @@ int rf_blade_recv_with_time(void *h,
|
|||
return nsamples;
|
||||
}
|
||||
|
||||
int rf_blade_send_timed_multi(void *h,
|
||||
void *data[4],
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
double frac_secs,
|
||||
bool has_time_spec,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst)
|
||||
{
|
||||
return rf_blade_send_timed(h, data[0], nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst,
|
||||
is_end_of_burst);
|
||||
}
|
||||
|
||||
int rf_blade_send_timed(void *h,
|
||||
void *data,
|
||||
int nsamples,
|
||||
|
|
|
@ -34,7 +34,7 @@ SRSLTE_API int rf_blade_open(char *args,
|
|||
void **handler);
|
||||
|
||||
SRSLTE_API int rf_blade_open_multi(char *args,
|
||||
void **handler, uint32_t nof_rx_antennas);
|
||||
void **handler, uint32_t nof_tx_antennas, uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API char* rf_blade_devname(void *h);
|
||||
|
||||
|
@ -111,6 +111,16 @@ SRSLTE_API void rf_blade_get_time(void *h,
|
|||
time_t *secs,
|
||||
double *frac_secs);
|
||||
|
||||
SRSLTE_API int rf_blade_send_timed_multi(void *h,
|
||||
void *data[4],
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
double frac_secs,
|
||||
bool has_time_spec,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst);
|
||||
|
||||
SRSLTE_API int rf_blade_send_timed(void *h,
|
||||
void *data,
|
||||
int nsamples,
|
||||
|
|
|
@ -38,7 +38,7 @@ typedef struct {
|
|||
void (*srslte_rf_suppress_stdout)(void *h);
|
||||
void (*srslte_rf_register_error_handler)(void *h, srslte_rf_error_handler_t error_handler);
|
||||
int (*srslte_rf_open)(char *args, void **h);
|
||||
int (*srslte_rf_open_multi)(char *args, void **h, uint32_t nof_rx_antennas);
|
||||
int (*srslte_rf_open_multi)(char *args, void **h, uint32_t nof_tx_antennas, uint32_t nof_rx_antennas);
|
||||
int (*srslte_rf_close)(void *h);
|
||||
void (*srslte_rf_set_master_clock_rate)(void *h, double rate);
|
||||
bool (*srslte_rf_is_master_clock_dynamic)(void *h);
|
||||
|
@ -58,6 +58,9 @@ typedef struct {
|
|||
int (*srslte_rf_send_timed)(void *h, void *data, int nsamples,
|
||||
time_t secs, double frac_secs, bool has_time_spec,
|
||||
bool blocking, bool is_start_of_burst, bool is_end_of_burst);
|
||||
int (*srslte_rf_send_timed_multi)(void *h, void *data[4], int nsamples,
|
||||
time_t secs, double frac_secs, bool has_time_spec,
|
||||
bool blocking, bool is_start_of_burst, bool is_end_of_burst);
|
||||
void (*srslte_rf_set_tx_cal)(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
void (*srslte_rf_set_rx_cal)(void *h, srslte_rf_cal_t *cal);
|
||||
|
@ -81,7 +84,7 @@ static rf_dev_t dev_uhd = {
|
|||
rf_uhd_suppress_stdout,
|
||||
rf_uhd_register_error_handler,
|
||||
rf_uhd_open,
|
||||
rf_uhd_open_multi,
|
||||
.srslte_rf_open_multi = rf_uhd_open_multi,
|
||||
rf_uhd_close,
|
||||
rf_uhd_set_master_clock_rate,
|
||||
rf_uhd_is_master_clock_dynamic,
|
||||
|
@ -97,6 +100,7 @@ static rf_dev_t dev_uhd = {
|
|||
rf_uhd_recv_with_time,
|
||||
rf_uhd_recv_with_time_multi,
|
||||
rf_uhd_send_timed,
|
||||
.srslte_rf_send_timed_multi = rf_uhd_send_timed_multi,
|
||||
rf_uhd_set_tx_cal,
|
||||
rf_uhd_set_rx_cal
|
||||
};
|
||||
|
@ -119,7 +123,7 @@ static rf_dev_t dev_blade = {
|
|||
rf_blade_suppress_stdout,
|
||||
rf_blade_register_error_handler,
|
||||
rf_blade_open,
|
||||
rf_blade_open_multi,
|
||||
.srslte_rf_open_multi = rf_blade_open_multi,
|
||||
rf_blade_close,
|
||||
rf_blade_set_master_clock_rate,
|
||||
rf_blade_is_master_clock_dynamic,
|
||||
|
@ -135,6 +139,7 @@ static rf_dev_t dev_blade = {
|
|||
rf_blade_recv_with_time,
|
||||
rf_blade_recv_with_time_multi,
|
||||
rf_blade_send_timed,
|
||||
.srslte_rf_send_timed_multi = rf_blade_send_timed_multi,
|
||||
rf_blade_set_tx_cal,
|
||||
rf_blade_set_rx_cal
|
||||
};
|
||||
|
@ -172,6 +177,7 @@ static rf_dev_t dev_soapy = {
|
|||
rf_soapy_recv_with_time,
|
||||
rf_soapy_recv_with_time_multi,
|
||||
rf_soapy_send_timed,
|
||||
.srslte_rf_send_timed_multi = /* FIXME: Implement srslte_rf_send_timed_multi for Soapy SDR */ NULL,
|
||||
rf_soapy_set_tx_cal,
|
||||
rf_soapy_set_rx_cal
|
||||
};
|
||||
|
|
|
@ -103,6 +103,10 @@ int srslte_rf_open_devname(srslte_rf_t *rf, char *devname, char *args) {
|
|||
}
|
||||
|
||||
int srslte_rf_open_devname_multi(srslte_rf_t *rf, char *devname, char *args, uint32_t nof_rx_antennas) {
|
||||
return srslte_rf_open_devname_multi2(rf, devname, args, 1, nof_rx_antennas);
|
||||
}
|
||||
|
||||
int srslte_rf_open_devname_multi2(srslte_rf_t *rf, char *devname, char *args, uint32_t nof_tx_antennas, uint32_t nof_rx_antennas) {
|
||||
/* Try to open the device if name is provided */
|
||||
if (devname) {
|
||||
if (devname[0] != '\0') {
|
||||
|
@ -110,7 +114,7 @@ int srslte_rf_open_devname_multi(srslte_rf_t *rf, char *devname, char *args, uin
|
|||
while(available_devices[i] != NULL) {
|
||||
if (!strcmp(available_devices[i]->name, devname)) {
|
||||
rf->dev = available_devices[i];
|
||||
return available_devices[i]->srslte_rf_open_multi(args, &rf->handler, nof_rx_antennas);
|
||||
return available_devices[i]->srslte_rf_open_multi(args, &rf->handler, nof_tx_antennas, nof_rx_antennas);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
@ -121,7 +125,7 @@ int srslte_rf_open_devname_multi(srslte_rf_t *rf, char *devname, char *args, uin
|
|||
/* If in auto mode or provided device not found, try to open in order of apperance in available_devices[] array */
|
||||
int i=0;
|
||||
while(available_devices[i] != NULL) {
|
||||
if (!available_devices[i]->srslte_rf_open_multi(args, &rf->handler, nof_rx_antennas)) {
|
||||
if (!available_devices[i]->srslte_rf_open_multi(args, &rf->handler, nof_tx_antennas, nof_rx_antennas)) {
|
||||
rf->dev = available_devices[i];
|
||||
return 0;
|
||||
}
|
||||
|
@ -194,6 +198,11 @@ int srslte_rf_open_multi(srslte_rf_t *h, char *args, uint32_t nof_rx_antennas)
|
|||
return srslte_rf_open_devname_multi(h, NULL, args, nof_rx_antennas);
|
||||
}
|
||||
|
||||
int srslte_rf_open_multi2(srslte_rf_t *h, char *args, uint32_t nof_tx_antennas, uint32_t nof_rx_antennas)
|
||||
{
|
||||
return srslte_rf_open_devname_multi2(h, NULL, args, nof_tx_antennas, nof_rx_antennas);
|
||||
}
|
||||
|
||||
int srslte_rf_close(srslte_rf_t *rf)
|
||||
{
|
||||
return ((rf_dev_t*) rf->dev)->srslte_rf_close(rf->handler);
|
||||
|
@ -301,6 +310,18 @@ int srslte_rf_send_timed3(srslte_rf_t *rf,
|
|||
has_time_spec, blocking, is_start_of_burst, is_end_of_burst);
|
||||
}
|
||||
|
||||
int srslte_rf_send_multi(srslte_rf_t *rf,
|
||||
void *data[4],
|
||||
int nsamples,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst)
|
||||
{
|
||||
|
||||
return ((rf_dev_t*) rf->dev)->srslte_rf_send_timed_multi(rf->handler, data, nsamples, 0, 0,
|
||||
false, blocking, is_start_of_burst, is_end_of_burst);
|
||||
}
|
||||
|
||||
int srslte_rf_send(srslte_rf_t *rf, void *data, uint32_t nsamples, bool blocking)
|
||||
{
|
||||
return srslte_rf_send2(rf, data, nsamples, blocking, true, true);
|
||||
|
|
|
@ -286,10 +286,10 @@ float rf_uhd_get_rssi(void *h) {
|
|||
|
||||
int rf_uhd_open(char *args, void **h)
|
||||
{
|
||||
return rf_uhd_open_multi(args, h, 1);
|
||||
return rf_uhd_open_multi(args, h, 1, 1);
|
||||
}
|
||||
|
||||
int rf_uhd_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
|
||||
int rf_uhd_open_multi(char *args, void **h, uint32_t nof_tx_antennas, uint32_t nof_rx_antennas)
|
||||
{
|
||||
if (h) {
|
||||
*h = NULL;
|
||||
|
@ -395,12 +395,11 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
|
|||
.otw_format = "sc16",
|
||||
.args = "",
|
||||
.channel_list = channel,
|
||||
.n_channels = 1
|
||||
.n_channels = (nof_tx_antennas > nof_rx_antennas)?nof_tx_antennas:nof_rx_antennas,
|
||||
};
|
||||
|
||||
handler->nof_rx_channels = nof_rx_antennas;
|
||||
handler->nof_tx_channels = 1;
|
||||
|
||||
handler->nof_tx_channels = nof_tx_antennas;
|
||||
/* Initialize rx and tx stremers */
|
||||
uhd_rx_streamer_make(&handler->rx_stream);
|
||||
error = uhd_usrp_get_rx_stream(handler->usrp, &stream_args, handler->rx_stream);
|
||||
|
@ -648,8 +647,28 @@ int rf_uhd_send_timed(void *h,
|
|||
bool is_start_of_burst,
|
||||
bool is_end_of_burst)
|
||||
{
|
||||
void *_data[SRSLTE_MAX_PORTS]= {data, zero_mem, zero_mem, zero_mem};
|
||||
|
||||
return rf_uhd_send_timed_multi(h, _data, nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst, is_end_of_burst);
|
||||
}
|
||||
|
||||
int rf_uhd_send_timed_multi(void *h,
|
||||
void *data[4],
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
double frac_secs,
|
||||
bool has_time_spec,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst) {
|
||||
rf_uhd_handler_t* handler = (rf_uhd_handler_t*) h;
|
||||
|
||||
/* Resets the USRP time FIXME: this might cause problems for burst transmissions */
|
||||
if (is_start_of_burst && handler->nof_tx_channels > 1) {
|
||||
uhd_usrp_set_time_now(handler->usrp, 0, 0, 0);
|
||||
uhd_tx_metadata_set_time_spec(&handler->tx_md, 0, 0.1);
|
||||
}
|
||||
|
||||
size_t txd_samples;
|
||||
if (has_time_spec) {
|
||||
uhd_tx_metadata_set_time_spec(&handler->tx_md, secs, frac_secs);
|
||||
|
@ -657,7 +676,10 @@ int rf_uhd_send_timed(void *h,
|
|||
int trials = 0;
|
||||
if (blocking) {
|
||||
int n = 0;
|
||||
cf_t *data_c = (cf_t*) data;
|
||||
cf_t *data_c[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
data_c[i] = data[i];
|
||||
}
|
||||
do {
|
||||
size_t tx_samples = handler->tx_nof_samples;
|
||||
|
||||
|
@ -675,9 +697,12 @@ int rf_uhd_send_timed(void *h,
|
|||
tx_samples = nsamples - n;
|
||||
uhd_tx_metadata_set_end(&handler->tx_md, is_end_of_burst);
|
||||
}
|
||||
|
||||
void *buff = (void*) &data_c[n];
|
||||
const void *buffs_ptr[4] = {buff, zero_mem, zero_mem, zero_mem};
|
||||
|
||||
const void *buffs_ptr[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
void *buff = (void*) &data_c[i][n];
|
||||
buffs_ptr[i] = buff;
|
||||
}
|
||||
uhd_error error = uhd_tx_streamer_send(handler->tx_stream, buffs_ptr,
|
||||
tx_samples, &handler->tx_md, 3.0, &txd_samples);
|
||||
if (error) {
|
||||
|
@ -691,7 +716,10 @@ int rf_uhd_send_timed(void *h,
|
|||
} while (n < nsamples && trials < 100);
|
||||
return nsamples;
|
||||
} else {
|
||||
const void *buffs_ptr[4] = {data, zero_mem, zero_mem, zero_mem};
|
||||
const void *buffs_ptr[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
buffs_ptr[i] = data[i];
|
||||
}
|
||||
uhd_tx_metadata_set_start(&handler->tx_md, is_start_of_burst);
|
||||
uhd_tx_metadata_set_end(&handler->tx_md, is_end_of_burst);
|
||||
return uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, nsamples, &handler->tx_md, 0.0, &txd_samples);
|
||||
|
|
|
@ -39,6 +39,7 @@ SRSLTE_API int rf_uhd_open(char *args,
|
|||
|
||||
SRSLTE_API int rf_uhd_open_multi(char *args,
|
||||
void **handler,
|
||||
uint32_t nof_tx_antennas,
|
||||
uint32_t nof_rx_antennas);
|
||||
|
||||
SRSLTE_API char* rf_uhd_devname(void *h);
|
||||
|
@ -123,3 +124,13 @@ SRSLTE_API int rf_uhd_send_timed(void *h,
|
|||
bool is_start_of_burst,
|
||||
bool is_end_of_burst);
|
||||
|
||||
SRSLTE_API int rf_uhd_send_timed_multi(void *h,
|
||||
void *data[SRSLTE_MAX_PORTS],
|
||||
int nsamples,
|
||||
time_t secs,
|
||||
double frac_secs,
|
||||
bool has_time_spec,
|
||||
bool blocking,
|
||||
bool is_start_of_burst,
|
||||
bool is_end_of_burst);
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
|
||||
|
||||
|
||||
static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // Only TM1 and TM2 are currently supported
|
||||
const uint32_t nof_ue_formats = 2;
|
||||
static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1, SRSLTE_DCI_FORMAT2A}; // Only TM1 and TM2 are currently supported
|
||||
const uint32_t nof_ue_formats = 3;
|
||||
|
||||
static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1C};
|
||||
const uint32_t nof_common_formats = 2;
|
||||
|
@ -97,13 +97,16 @@ int srslte_ue_dl_init_multi(srslte_ue_dl_t *q,
|
|||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_pdsch_init_multi(&q->pdsch, q->cell, nof_rx_antennas)) {
|
||||
if (srslte_pdsch_init_rx_multi(&q->pdsch, q->cell, nof_rx_antennas)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
goto clean_exit;
|
||||
|
||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
if (srslte_softbuffer_rx_init(&q->softbuffers[i], q->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating soft buffer\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
}
|
||||
if (srslte_cfo_init(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) {
|
||||
fprintf(stderr, "Error initiating SFO correct\n");
|
||||
|
@ -154,7 +157,9 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
|
|||
srslte_pdcch_free(&q->pdcch);
|
||||
srslte_pdsch_free(&q->pdsch);
|
||||
srslte_cfo_free(&q->sfo_correct);
|
||||
srslte_softbuffer_rx_free(&q->softbuffer);
|
||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||
srslte_softbuffer_rx_free(&q->softbuffers[i]);
|
||||
}
|
||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||
if (q->sf_symbols_m[j]) {
|
||||
free(q->sf_symbols_m[j]);
|
||||
|
@ -188,7 +193,9 @@ void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) {
|
|||
}
|
||||
|
||||
void srslte_ue_dl_reset(srslte_ue_dl_t *q) {
|
||||
srslte_softbuffer_rx_reset(&q->softbuffer);
|
||||
for(int i = 0; i < SRSLTE_MAX_CODEWORDS; i++){
|
||||
srslte_softbuffer_rx_reset(&q->softbuffers[i]);
|
||||
}
|
||||
bzero(&q->pdsch_cfg, sizeof(srslte_pdsch_cfg_t));
|
||||
}
|
||||
|
||||
|
@ -204,12 +211,14 @@ void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, float sample_offset) {
|
|||
* - PDSCH decoding: Decode TB scrambling with RNTI given by srslte_ue_dl_set_rnti()
|
||||
*/
|
||||
int srslte_ue_dl_decode(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti) {
|
||||
uint8_t *_data[SRSLTE_MAX_CODEWORDS];
|
||||
cf_t *_input[SRSLTE_MAX_PORTS];
|
||||
_data[0] = data;
|
||||
_input[0] = input;
|
||||
return srslte_ue_dl_decode_rnti_multi(q, _input, data, tti, q->current_rnti);
|
||||
return srslte_ue_dl_decode_rnti_multi(q, _input, _data, tti, q->current_rnti);
|
||||
}
|
||||
|
||||
int srslte_ue_dl_decode_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data, uint32_t tti) {
|
||||
int srslte_ue_dl_decode_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data[SRSLTE_MAX_CODEWORDS], uint32_t tti) {
|
||||
return srslte_ue_dl_decode_rnti_multi(q, input, data, tti, q->current_rnti);
|
||||
}
|
||||
|
||||
|
@ -275,17 +284,24 @@ int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *c
|
|||
|
||||
int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint32_t rvidx)
|
||||
{
|
||||
return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx);
|
||||
return srslte_pdsch_cfg_multi(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx, 0);
|
||||
}
|
||||
|
||||
int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti, uint16_t rnti)
|
||||
int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint32_t rvidx, uint32_t rvidx2)
|
||||
{
|
||||
return srslte_pdsch_cfg_multi(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx, rvidx2);
|
||||
}
|
||||
|
||||
int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti, uint16_t rnti)
|
||||
{
|
||||
uint8_t *_data[SRSLTE_MAX_CODEWORDS];
|
||||
cf_t *_input[SRSLTE_MAX_PORTS];
|
||||
_input[0] = input;
|
||||
return srslte_ue_dl_decode_rnti_multi(q, _input, data, tti, rnti);
|
||||
_data[0] = data;
|
||||
return srslte_ue_dl_decode_rnti_multi(q, _input, _data, tti, rnti);
|
||||
}
|
||||
|
||||
int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data, uint32_t tti, uint16_t rnti)
|
||||
int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data[SRSLTE_MAX_CODEWORDS], uint32_t tti, uint16_t rnti)
|
||||
{
|
||||
srslte_dci_msg_t dci_msg;
|
||||
srslte_ra_dl_dci_t dci_unpacked;
|
||||
|
@ -320,17 +336,26 @@ int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_POR
|
|||
|
||||
|
||||
uint32_t rvidx = 0;
|
||||
uint32_t rvidx2 = 0;
|
||||
if (dci_unpacked.rv_idx < 0) {
|
||||
uint32_t sfn = tti/10;
|
||||
uint32_t k = (sfn/2)%4;
|
||||
rvidx = ((uint32_t) ceilf((float)1.5*k))%4;
|
||||
srslte_softbuffer_rx_reset_tbs(&q->softbuffer, grant.mcs.tbs);
|
||||
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[0], (uint32_t) grant.mcs.tbs);
|
||||
if (grant.nof_tb > 1) {
|
||||
rvidx2 = ((uint32_t) ceilf((float)1.5*k))%4;
|
||||
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[1], (uint32_t) grant.mcs2.tbs);
|
||||
}
|
||||
} else {
|
||||
rvidx = dci_unpacked.rv_idx;
|
||||
srslte_softbuffer_rx_reset_tbs(&q->softbuffer, grant.mcs.tbs);
|
||||
rvidx = (uint32_t) dci_unpacked.rv_idx;
|
||||
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[0], (uint32_t) grant.mcs.tbs);
|
||||
if (grant.nof_tb > 1) {
|
||||
rvidx2 = (uint32_t) dci_unpacked.rv_idx_1;
|
||||
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[1], (uint32_t) grant.mcs2.tbs);
|
||||
}
|
||||
}
|
||||
|
||||
if (srslte_ue_dl_cfg_grant(q, &grant, cfi, sf_idx, rvidx)) {
|
||||
if (srslte_ue_dl_cfg_grant_multi(q, &grant, cfi, sf_idx, rvidx, rvidx2)) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
|
@ -340,7 +365,7 @@ int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_POR
|
|||
|
||||
|
||||
if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) {
|
||||
ret = srslte_pdsch_decode_multi(&q->pdsch, &q->pdsch_cfg, &q->softbuffer,
|
||||
ret = srslte_pdsch_decode_multi(&q->pdsch, &q->pdsch_cfg, q->softbuffers,
|
||||
q->sf_symbols_m, q->ce_m,
|
||||
noise_estimate,
|
||||
rnti, data);
|
||||
|
|
|
@ -53,6 +53,11 @@ cf_t dummy_buffer1[15*2048/2];
|
|||
cf_t *dummy_offset_buffer[SRSLTE_MAX_PORTS] = {dummy_buffer0, dummy_buffer1};
|
||||
|
||||
int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset_time, float offset_freq) {
|
||||
return srslte_ue_sync_init_file_multi(q, nof_prb, file_name, offset_time, offset_freq, 1);
|
||||
}
|
||||
|
||||
int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset_time,
|
||||
float offset_freq, uint32_t nof_rx_ant) {
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
|
@ -66,6 +71,7 @@ int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_n
|
|||
q->file_cfo = -offset_freq;
|
||||
q->correct_cfo = true;
|
||||
q->fft_size = srslte_symbol_sz(nof_prb);
|
||||
q->nof_rx_antennas = nof_rx_ant;
|
||||
|
||||
if (srslte_cfo_init(&q->file_cfo_correct, 2*q->sf_len)) {
|
||||
fprintf(stderr, "Error initiating CFO\n");
|
||||
|
@ -80,12 +86,12 @@ int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_n
|
|||
INFO("Offseting input file by %d samples and %.1f kHz\n", offset_time, offset_freq/1000);
|
||||
|
||||
if (offset_time) {
|
||||
cf_t *file_offset_buffer = srslte_vec_malloc(offset_time * sizeof(cf_t));
|
||||
cf_t *file_offset_buffer = srslte_vec_malloc(offset_time * nof_rx_ant * sizeof(cf_t));
|
||||
if (!file_offset_buffer) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
srslte_filesource_read(&q->file_source, file_offset_buffer, offset_time);
|
||||
srslte_filesource_read(&q->file_source, file_offset_buffer, offset_time * nof_rx_ant);
|
||||
free(file_offset_buffer);
|
||||
}
|
||||
|
||||
|
@ -518,26 +524,27 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
|
|||
{
|
||||
|
||||
if (q->file_mode) {
|
||||
int n = srslte_filesource_read(&q->file_source, input_buffer[0], q->sf_len);
|
||||
int n = srslte_filesource_read_multi(&q->file_source, (void **) input_buffer, q->sf_len, q->nof_rx_antennas);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error reading input file\n");
|
||||
return SRSLTE_ERROR;
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
if (n == 0) {
|
||||
srslte_filesource_seek(&q->file_source, 0);
|
||||
q->sf_idx = 9;
|
||||
int n = srslte_filesource_read(&q->file_source, input_buffer[0], q->sf_len);
|
||||
q->sf_idx = 9;
|
||||
n = srslte_filesource_read_multi(&q->file_source, (void **) input_buffer, q->sf_len, q->nof_rx_antennas);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error reading input file\n");
|
||||
return SRSLTE_ERROR;
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
if (q->correct_cfo) {
|
||||
srslte_cfo_correct(&q->file_cfo_correct,
|
||||
input_buffer[0],
|
||||
input_buffer[0],
|
||||
q->file_cfo / 15000 / q->fft_size);
|
||||
|
||||
for (int i = 0; i < q->nof_rx_antennas; i++) {
|
||||
srslte_cfo_correct(&q->file_cfo_correct,
|
||||
input_buffer[i],
|
||||
input_buffer[i],
|
||||
q->file_cfo / 15000 / q->fft_size);
|
||||
}
|
||||
}
|
||||
q->sf_idx++;
|
||||
if (q->sf_idx == 10) {
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant);
|
||||
bool decode_phich(bool *ack);
|
||||
bool decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload, srslte_softbuffer_rx_t* softbuffer, int rv, uint16_t rnti, uint32_t pid);
|
||||
bool decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSLTE_MAX_CODEWORDS], srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS], int rv, uint16_t rnti, uint32_t pid);
|
||||
|
||||
/* ... for UL */
|
||||
void encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, uint32_t current_tx_nb, srslte_softbuffer_tx_t *softbuffer,
|
||||
|
|
|
@ -405,8 +405,14 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
|
|||
}
|
||||
}
|
||||
|
||||
bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
|
||||
bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
|
||||
srslte_softbuffer_rx_t* softbuffer, int rv, uint16_t rnti, uint32_t harq_pid)
|
||||
{
|
||||
return decode_pdsch_multi(grant, &payload, softbuffer, rv, rnti, harq_pid);
|
||||
}
|
||||
|
||||
bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSLTE_MAX_CODEWORDS],
|
||||
srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS], int rv, uint16_t rnti, uint32_t harq_pid)
|
||||
{
|
||||
char timestr[64];
|
||||
timestr[0]='\0';
|
||||
|
@ -435,7 +441,7 @@ bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
|
|||
gettimeofday(&t[1], NULL);
|
||||
#endif
|
||||
|
||||
bool ack = srslte_pdsch_decode_multi(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols_m,
|
||||
bool ack = srslte_pdsch_decode_multi(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffers, ue_dl.sf_symbols_m,
|
||||
ue_dl.ce_m, noise_estimate, rnti, payload) == 0;
|
||||
#ifdef LOG_EXECTIME
|
||||
gettimeofday(&t[2], NULL);
|
||||
|
|
Loading…
Reference in New Issue