mirror of https://github.com/pvnis/srsRAN_4G.git
add tdd/ca support
parent
963a5faad0
commit
7780b1aba5
@ -1,421 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \section COPYRIGHT
|
|
||||||
*
|
|
||||||
* Copyright 2013-2015 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* \section LICENSE
|
|
||||||
*
|
|
||||||
* This file is part of the srsLTE library.
|
|
||||||
*
|
|
||||||
* srsLTE is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* srsLTE is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* A copy of the GNU Affero General Public License can be found in
|
|
||||||
* the LICENSE file in the top-level directory of this distribution
|
|
||||||
* and at http://www.gnu.org/licenses/.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#define ENABLE_AGC_DEFAULT
|
|
||||||
|
|
||||||
#include "srslte/srslte.h"
|
|
||||||
#include "srslte/phy/rf/rf.h"
|
|
||||||
#include "srslte/phy/rf/rf_utils.h"
|
|
||||||
#include "srslte/common/crash_handler.h"
|
|
||||||
|
|
||||||
cell_search_cfg_t cell_detect_config = {
|
|
||||||
SRSLTE_DEFAULT_MAX_FRAMES_PBCH,
|
|
||||||
SRSLTE_DEFAULT_MAX_FRAMES_PSS,
|
|
||||||
SRSLTE_DEFAULT_NOF_VALID_PSS_FRAMES,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
* Program arguments processing
|
|
||||||
***********************************************************************/
|
|
||||||
typedef struct {
|
|
||||||
int nof_subframes;
|
|
||||||
bool disable_plots;
|
|
||||||
int force_N_id_2;
|
|
||||||
char *rf_args;
|
|
||||||
float rf_freq;
|
|
||||||
float rf_gain;
|
|
||||||
}prog_args_t;
|
|
||||||
|
|
||||||
void args_default(prog_args_t *args) {
|
|
||||||
args->nof_subframes = -1;
|
|
||||||
args->force_N_id_2 = -1; // Pick the best
|
|
||||||
args->rf_args = "";
|
|
||||||
args->rf_freq = -1.0;
|
|
||||||
#ifdef ENABLE_AGC_DEFAULT
|
|
||||||
args->rf_gain = -1;
|
|
||||||
#else
|
|
||||||
args->rf_gain = 50;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void usage(prog_args_t *args, char *prog) {
|
|
||||||
printf("Usage: %s [aglnv] -f rx_frequency (in Hz)\n", prog);
|
|
||||||
printf("\t-a RF args [Default %s]\n", args->rf_args);
|
|
||||||
printf("\t-g RF RX gain [Default %.2f dB]\n", args->rf_gain);
|
|
||||||
printf("\t-l Force N_id_2 [Default best]\n");
|
|
||||||
printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes);
|
|
||||||
printf("\t-v [set srslte_verbose to debug, default none]\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_args(prog_args_t *args, int argc, char **argv) {
|
|
||||||
int opt;
|
|
||||||
args_default(args);
|
|
||||||
while ((opt = getopt(argc, argv, "aglnvf")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'a':
|
|
||||||
args->rf_args = argv[optind];
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
args->rf_gain = atof(argv[optind]);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
args->rf_freq = atof(argv[optind]);
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
args->nof_subframes = atoi(argv[optind]);
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
args->force_N_id_2 = atoi(argv[optind]);
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
srslte_verbose++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage(args, argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (args->rf_freq < 0) {
|
|
||||||
usage(args, argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/**********************************************************************/
|
|
||||||
|
|
||||||
/* TODO: Do something with the output data */
|
|
||||||
uint8_t *data[SRSLTE_MAX_CODEWORDS];
|
|
||||||
|
|
||||||
bool go_exit = false;
|
|
||||||
void sig_int_handler(int signo)
|
|
||||||
{
|
|
||||||
printf("SIGINT received. Exiting...\n");
|
|
||||||
if (signo == SIGINT) {
|
|
||||||
go_exit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *q) {
|
|
||||||
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
|
|
||||||
|
|
||||||
return srslte_rf_recv(h, data[0], nsamples, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state;
|
|
||||||
|
|
||||||
#define MAX_SINFO 10
|
|
||||||
#define MAX_NEIGHBOUR_CELLS 128
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
int ret;
|
|
||||||
cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL, NULL};
|
|
||||||
prog_args_t prog_args;
|
|
||||||
srslte_cell_t cell;
|
|
||||||
int64_t sf_cnt;
|
|
||||||
srslte_ue_sync_t ue_sync;
|
|
||||||
srslte_ue_mib_t ue_mib;
|
|
||||||
srslte_rf_t rf;
|
|
||||||
srslte_ue_dl_t ue_dl;
|
|
||||||
srslte_ofdm_t fft;
|
|
||||||
srslte_chest_dl_t chest;
|
|
||||||
uint32_t nframes=0;
|
|
||||||
uint32_t nof_trials = 0;
|
|
||||||
uint32_t sfn = 0; // system frame number
|
|
||||||
int n;
|
|
||||||
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
|
||||||
int sfn_offset;
|
|
||||||
float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0;
|
|
||||||
cf_t *ce[SRSLTE_MAX_PORTS];
|
|
||||||
float cfo = 0;
|
|
||||||
bool acks[SRSLTE_MAX_CODEWORDS] = {false};
|
|
||||||
|
|
||||||
srslte_debug_handle_crash(argc, argv);
|
|
||||||
|
|
||||||
if (parse_args(&prog_args, argc, argv)) {
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Opening RF device...\n");
|
|
||||||
if (srslte_rf_open(&rf, prog_args.rf_args)) {
|
|
||||||
fprintf(stderr, "Error opening rf\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
if (prog_args.rf_gain > 0) {
|
|
||||||
srslte_rf_set_rx_gain(&rf, prog_args.rf_gain);
|
|
||||||
} else {
|
|
||||||
printf("Starting AGC thread...\n");
|
|
||||||
if (srslte_rf_start_gain_thread(&rf, false)) {
|
|
||||||
fprintf(stderr, "Error opening rf\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
srslte_rf_set_rx_gain(&rf, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
|
|
||||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
|
||||||
data[i] = srslte_vec_malloc(sizeof(uint8_t) * 1500*8);
|
|
||||||
}
|
|
||||||
|
|
||||||
sigset_t sigset;
|
|
||||||
sigemptyset(&sigset);
|
|
||||||
sigaddset(&sigset, SIGINT);
|
|
||||||
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
|
|
||||||
signal(SIGINT, sig_int_handler);
|
|
||||||
|
|
||||||
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
|
|
||||||
|
|
||||||
/* set receiver frequency */
|
|
||||||
srslte_rf_set_rx_freq(&rf, (double) prog_args.rf_freq);
|
|
||||||
srslte_rf_rx_wait_lo_locked(&rf);
|
|
||||||
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.rf_freq/1000000);
|
|
||||||
|
|
||||||
cell_detect_config.init_agc = (prog_args.rf_gain<0);
|
|
||||||
|
|
||||||
uint32_t ntrial=0;
|
|
||||||
do {
|
|
||||||
ret = rf_search_and_decode_mib(&rf, 1, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "Error searching for cell\n");
|
|
||||||
exit(-1);
|
|
||||||
} else if (ret == 0 && !go_exit) {
|
|
||||||
printf("Cell not found after %d trials. Trying again (Press Ctrl+C to exit)\n", ntrial++);
|
|
||||||
}
|
|
||||||
} while (ret == 0 && !go_exit);
|
|
||||||
|
|
||||||
if (go_exit) {
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set sampling frequency */
|
|
||||||
int srate = srslte_sampling_freq_hz(cell.nof_prb);
|
|
||||||
if (srate != -1) {
|
|
||||||
if (srate < 10e6) {
|
|
||||||
srslte_rf_set_master_clock_rate(&rf, 4*srate);
|
|
||||||
} else {
|
|
||||||
srslte_rf_set_master_clock_rate(&rf, srate);
|
|
||||||
}
|
|
||||||
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
|
|
||||||
float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate);
|
|
||||||
if (srate_rf != srate) {
|
|
||||||
fprintf(stderr, "Could not set sampling rate\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO("Stopping RF and flushing buffer...\n");
|
|
||||||
srslte_rf_stop_rx_stream(&rf);
|
|
||||||
srslte_rf_flush_buffer(&rf);
|
|
||||||
|
|
||||||
if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
|
|
||||||
fprintf(stderr, "Error initiating ue_sync\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
|
|
||||||
fprintf(stderr, "Error initiating ue_sync\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, 1)) {
|
|
||||||
fprintf(stderr, "Error initiating UE downlink processing module\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
|
|
||||||
fprintf(stderr, "Error initiating UE downlink processing module\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) {
|
|
||||||
fprintf(stderr, "Error initaiting UE MIB decoder\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
|
|
||||||
fprintf(stderr, "Error initaiting UE MIB decoder\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
|
|
||||||
srslte_ue_dl_set_rnti(&ue_dl, SRSLTE_SIRNTI);
|
|
||||||
|
|
||||||
/* Initialize subframe counter */
|
|
||||||
sf_cnt = 0;
|
|
||||||
|
|
||||||
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
|
|
||||||
|
|
||||||
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
|
|
||||||
|
|
||||||
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
|
|
||||||
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srslte_ofdm_rx_init(&fft, cell.cp, sf_buffer[0], sf_symbols, cell.nof_prb)) {
|
|
||||||
fprintf(stderr, "Error initiating FFT\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
|
|
||||||
fprintf(stderr, "Error initiating channel estimator\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (srslte_chest_dl_set_cell(&chest, cell)) {
|
|
||||||
fprintf(stderr, "Error initiating channel estimator\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
srslte_rf_start_rx_stream(&rf, false);
|
|
||||||
|
|
||||||
float rx_gain_offset = 0;
|
|
||||||
|
|
||||||
/* Main loop */
|
|
||||||
while ((sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) && !go_exit) {
|
|
||||||
|
|
||||||
ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
|
|
||||||
if (ret == 1) {
|
|
||||||
switch (state) {
|
|
||||||
case DECODE_MIB:
|
|
||||||
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
|
|
||||||
srslte_pbch_decode_reset(&ue_mib.pbch);
|
|
||||||
n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
|
|
||||||
if (n < 0) {
|
|
||||||
fprintf(stderr, "Error decoding UE MIB\n");
|
|
||||||
return -1;
|
|
||||||
} else if (n == SRSLTE_UE_MIB_FOUND) {
|
|
||||||
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
|
|
||||||
printf("Decoded MIB. SFN: %d, offset: %d\n", sfn, sfn_offset);
|
|
||||||
sfn = (sfn + sfn_offset)%1024;
|
|
||||||
state = DECODE_SIB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DECODE_SIB:
|
|
||||||
/* We are looking for SI Blocks, search only in appropiate places */
|
|
||||||
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
|
|
||||||
n = srslte_ue_dl_decode(&ue_dl, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks);
|
|
||||||
if (n < 0) {
|
|
||||||
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
|
|
||||||
return -1;
|
|
||||||
} else if (n == 0) {
|
|
||||||
printf("CFO: %+6.4f kHz, SFO: %+6.4f kHz, PDCCH-Det: %.3f\r",
|
|
||||||
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
|
|
||||||
(float) ue_dl.nof_detected/nof_trials);
|
|
||||||
nof_trials++;
|
|
||||||
} else {
|
|
||||||
printf("Decoded SIB1. Payload: ");
|
|
||||||
srslte_vec_fprint_byte(stdout, data[0], n/8);;
|
|
||||||
state = MEASURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MEASURE:
|
|
||||||
|
|
||||||
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
|
|
||||||
/* Run FFT for all subframe data */
|
|
||||||
srslte_ofdm_rx_sf(&fft);
|
|
||||||
|
|
||||||
srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync));
|
|
||||||
|
|
||||||
rssi = SRSLTE_VEC_EMA(srslte_vec_avg_power_cf(sf_buffer[0],SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb))),rssi,0.05);
|
|
||||||
rssi_utra = SRSLTE_VEC_EMA(srslte_chest_dl_get_rssi(&chest),rssi_utra,0.05);
|
|
||||||
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&chest),rsrq,0.05);
|
|
||||||
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&chest),rsrp,0.05);
|
|
||||||
snr = SRSLTE_VEC_EMA(srslte_chest_dl_get_snr(&chest),snr,0.05);
|
|
||||||
|
|
||||||
nframes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ((nframes%100) == 0 || rx_gain_offset == 0) {
|
|
||||||
if (srslte_rf_has_rssi(&rf)) {
|
|
||||||
rx_gain_offset = 30+10*log10(rssi*1000)-srslte_rf_get_rssi(&rf);
|
|
||||||
} else {
|
|
||||||
rx_gain_offset = srslte_rf_get_rx_gain(&rf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Plot and Printf
|
|
||||||
if ((nframes%10) == 0) {
|
|
||||||
|
|
||||||
printf("CFO: %+8.4f kHz, SFO: %+8.4f Hz, RSSI: %5.1f dBm, RSSI/ref-symbol: %+5.1f dBm, "
|
|
||||||
"RSRP: %+5.1f dBm, RSRQ: %5.1f dB, SNR: %5.1f dB\r",
|
|
||||||
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync),
|
|
||||||
10*log10(rssi*1000) - rx_gain_offset,
|
|
||||||
10*log10(rssi_utra*1000)- rx_gain_offset,
|
|
||||||
10*log10(rsrp*1000) - rx_gain_offset,
|
|
||||||
10*log10(rsrq), 10*log10(snr));
|
|
||||||
if (srslte_verbose != SRSLTE_VERBOSE_NONE) {
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) {
|
|
||||||
sfn++;
|
|
||||||
if (sfn == 1024) {
|
|
||||||
sfn = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (ret == 0) {
|
|
||||||
printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r",
|
|
||||||
srslte_sync_get_peak_value(&ue_sync.sfind),
|
|
||||||
ue_sync.frame_total_cnt, ue_sync.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sf_cnt++;
|
|
||||||
} // Main loop
|
|
||||||
|
|
||||||
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
|
||||||
if (data[i]) {
|
|
||||||
free(data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
srslte_ue_sync_free(&ue_sync);
|
|
||||||
srslte_rf_close(&rf);
|
|
||||||
printf("\nBye\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,329 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_DYN_BITSET_H
|
||||||
|
#define SRSLTE_DYN_BITSET_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define CEILFRAC(x, y) ((((x)-1) / (y)) + 1)
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
template <size_t N, bool reversed = false>
|
||||||
|
class bounded_bitset
|
||||||
|
{
|
||||||
|
typedef uint64_t word_t;
|
||||||
|
static const size_t bits_per_word = 8 * sizeof(word_t);
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr bounded_bitset() : buffer(), cur_size(0) {}
|
||||||
|
|
||||||
|
constexpr bounded_bitset(size_t cur_size_) : buffer(), cur_size(cur_size_) {}
|
||||||
|
|
||||||
|
constexpr size_t max_size() const noexcept { return N; }
|
||||||
|
|
||||||
|
size_t size() const noexcept { return cur_size; }
|
||||||
|
|
||||||
|
void resize(size_t new_size) noexcept
|
||||||
|
{
|
||||||
|
if (new_size > max_size()) {
|
||||||
|
printf("ERROR: bitset resize out of bounds: %lu>=%lu\n", max_size(), new_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur_size = new_size;
|
||||||
|
sanitize_();
|
||||||
|
for (size_t i = nof_words_(); i < sizeof(buffer); ++i) {
|
||||||
|
get_word_(i) = static_cast<word_t>(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(size_t pos) noexcept
|
||||||
|
{
|
||||||
|
if (pos >= size()) {
|
||||||
|
printf("ERROR: bitset out of bounds: %lu>=%lu\n", pos, size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos = reversed ? size() - 1 - pos : pos;
|
||||||
|
get_word_(pos) |= maskbit(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(size_t pos) noexcept
|
||||||
|
{
|
||||||
|
if (pos >= size()) {
|
||||||
|
printf("ERROR: bitset out of bounds: %lu>=%lu\n", pos, size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos = reversed ? size() - 1 - pos : pos;
|
||||||
|
get_word_(pos) &= ~(maskbit(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() noexcept
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < nof_words_(); ++i) {
|
||||||
|
buffer[i] = static_cast<word_t>(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test(size_t pos) const noexcept
|
||||||
|
{
|
||||||
|
if (pos >= size()) {
|
||||||
|
printf("ERROR: bitset out of bounds: %lu>=%lu\n", pos, size());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return test_(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bounded_bitset<N, reversed>& flip() noexcept
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < nof_words_(); ++i) {
|
||||||
|
buffer[i] = ~buffer[i];
|
||||||
|
}
|
||||||
|
sanitize_();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounded_bitset<N, reversed>& fill(size_t startpos, size_t endpos, bool value = true) noexcept
|
||||||
|
{
|
||||||
|
if (endpos > size() or startpos > endpos) {
|
||||||
|
printf("ERROR: bounds (%lu, %lu) are not valid for bitset of size: %lu\n", startpos, endpos, size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// NOTE: can be optimized
|
||||||
|
if (value) {
|
||||||
|
for (size_t i = startpos; i < endpos; ++i) {
|
||||||
|
set(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t i = startpos; i < endpos; ++i) {
|
||||||
|
reset(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool all() const noexcept
|
||||||
|
{
|
||||||
|
const size_t nw = nof_words_();
|
||||||
|
if (nw == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
word_t allset = ~static_cast<word_t>(0);
|
||||||
|
for (size_t i = 0; i < nw - 1; i++) {
|
||||||
|
if (buffer[i] != allset) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer[nw - 1] == (allset >> (nw * bits_per_word - size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool any() const noexcept
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < nof_words_(); ++i) {
|
||||||
|
if (buffer[i] != static_cast<word_t>(0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool any(size_t start, size_t stop) const noexcept
|
||||||
|
{
|
||||||
|
if (start > stop or stop > size()) {
|
||||||
|
printf("ERROR: bounds (%lu, %lu) are not valid for bitset of size: %lu\n", start, stop, size());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// NOTE: can be optimized
|
||||||
|
for (size_t i = start; i < stop; ++i) {
|
||||||
|
if (test_(i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool none() const noexcept { return !any(); }
|
||||||
|
|
||||||
|
size_t count() const noexcept
|
||||||
|
{
|
||||||
|
size_t result = 0;
|
||||||
|
for (size_t i = 0; i < nof_words_(); i++) {
|
||||||
|
// result += __builtin_popcountl(buffer[i]);
|
||||||
|
word_t w = buffer[i];
|
||||||
|
for (; w; w >>= 1) {
|
||||||
|
result += (w & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(bounded_bitset<N, reversed>& other) const noexcept
|
||||||
|
{
|
||||||
|
if (size() != other.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < nof_words_(); ++i) {
|
||||||
|
if (buffer[i] != other.buffer[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(bounded_bitset<N, reversed>& other) const noexcept { return not(*this == other); }
|
||||||
|
|
||||||
|
bounded_bitset<N, reversed>& operator|=(const bounded_bitset<N, reversed>& other) noexcept
|
||||||
|
{
|
||||||
|
if (other.size() != size()) {
|
||||||
|
printf("ERROR: operator|= called for bitsets of different sizes (%lu!=%lu)\n", size(), other.size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < nof_words_(); ++i) {
|
||||||
|
buffer[i] |= other.buffer[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounded_bitset<N, reversed>& operator&=(const bounded_bitset<N, reversed>& other) noexcept
|
||||||
|
{
|
||||||
|
if (other.size() != size()) {
|
||||||
|
printf("ERROR: operator&= called for bitsets of different sizes (%lu!=%lu)\n", size(), other.size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < nof_words_(); ++i) {
|
||||||
|
buffer[i] &= other.buffer[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounded_bitset<N, reversed> operator~() const noexcept
|
||||||
|
{
|
||||||
|
bounded_bitset<N, reversed> ret(*this);
|
||||||
|
ret.flip();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string to_string() const noexcept
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
s.assign(size(), '0');
|
||||||
|
if (not reversed) {
|
||||||
|
for (size_t i = size(); i > 0; --i) {
|
||||||
|
if (test(i - 1)) {
|
||||||
|
s[size() - i] = '1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < size(); ++i) {
|
||||||
|
if (test(i)) {
|
||||||
|
s[i] = '1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t to_uint64() const noexcept
|
||||||
|
{
|
||||||
|
if (nof_words_() > 1) {
|
||||||
|
printf("ERROR: cannot convert bitset of size %lu bits to uint64_t\n", size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return get_word_(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string to_hex() const noexcept
|
||||||
|
{
|
||||||
|
size_t nof_digits = (size() - 1) / 4 + 1;
|
||||||
|
char cstr[CEILFRAC(CEILFRAC(N, bits_per_word) * bits_per_word, 4) + 1];
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
for (int i = nof_words_() - 1; i >= 0; --i) {
|
||||||
|
count += sprintf(&cstr[count], "%016lx", buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t skip = nof_words_() * bits_per_word / 4 - nof_digits;
|
||||||
|
// printf("bitstring: %s\n", to_string().c_str());
|
||||||
|
return std::string(&cstr[skip], &cstr[nof_digits + skip + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
word_t buffer[(N - 1) / bits_per_word + 1];
|
||||||
|
size_t cur_size;
|
||||||
|
|
||||||
|
void sanitize_()
|
||||||
|
{
|
||||||
|
if (N % bits_per_word != 0) {
|
||||||
|
buffer[nof_words_() - 1] &= ~((~static_cast<word_t>(0)) << (size() % bits_per_word));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_(size_t pos) const noexcept
|
||||||
|
{
|
||||||
|
pos = reversed ? size() - 1 - pos : pos;
|
||||||
|
return ((get_word_(pos) & maskbit(pos)) != static_cast<word_t>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nof_words_() const noexcept { return size() > 0 ? (size() - 1) / bits_per_word + 1 : 0; }
|
||||||
|
|
||||||
|
word_t& get_word_(size_t pos) noexcept { return buffer[pos / bits_per_word]; }
|
||||||
|
|
||||||
|
const word_t& get_word_(size_t pos) const { return buffer[pos / bits_per_word]; }
|
||||||
|
|
||||||
|
size_t word_idx_(size_t pos) const { return pos / bits_per_word; }
|
||||||
|
|
||||||
|
static word_t maskbit(size_t pos) { return (static_cast<word_t>(1)) << (pos % bits_per_word); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t N, bool reversed>
|
||||||
|
inline bounded_bitset<N, reversed> operator&(const bounded_bitset<N, reversed>& lhs,
|
||||||
|
const bounded_bitset<N, reversed>& rhs)noexcept
|
||||||
|
{
|
||||||
|
bounded_bitset<N, reversed> res(lhs);
|
||||||
|
res &= rhs;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N, bool reversed>
|
||||||
|
inline bounded_bitset<N, reversed> operator|(const bounded_bitset<N, reversed>& lhs,
|
||||||
|
const bounded_bitset<N, reversed>& rhs) noexcept
|
||||||
|
{
|
||||||
|
bounded_bitset<N, reversed> res(lhs);
|
||||||
|
res |= rhs;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N, bool reversed>
|
||||||
|
inline bounded_bitset<N, reversed> fliplr(const bounded_bitset<N, reversed>& other) noexcept
|
||||||
|
{
|
||||||
|
bounded_bitset<N, reversed> ret(other.size());
|
||||||
|
ret.reset();
|
||||||
|
for (uint32_t i = 0; i < ret.size(); ++i) {
|
||||||
|
if (other.test(i)) {
|
||||||
|
ret.set(ret.size() - 1 - i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_DYN_BITSET_H
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_PUCCH_CFG_H
|
||||||
|
#define SRSLTE_PUCCH_CFG_H
|
||||||
|
|
||||||
|
#include "srslte/phy/phch/cqi.h"
|
||||||
|
#include "srslte/phy/phch/ra.h"
|
||||||
|
#include "srslte/phy/phch/uci_cfg.h"
|
||||||
|
|
||||||
|
#define SRSLTE_PUCCH_SIZE_AN_CS 4
|
||||||
|
#define SRSLTE_PUCCH_NOF_AN_CS 2
|
||||||
|
#define SRSLTE_PUCCH2_MAX_DMRS_BITS 16
|
||||||
|
|
||||||
|
typedef enum SRSLTE_API {
|
||||||
|
SRSLTE_PUCCH_FORMAT_1 = 0,
|
||||||
|
SRSLTE_PUCCH_FORMAT_1A,
|
||||||
|
SRSLTE_PUCCH_FORMAT_1B,
|
||||||
|
SRSLTE_PUCCH_FORMAT_2,
|
||||||
|
SRSLTE_PUCCH_FORMAT_2A,
|
||||||
|
SRSLTE_PUCCH_FORMAT_2B,
|
||||||
|
SRSLTE_PUCCH_FORMAT_3,
|
||||||
|
SRSLTE_PUCCH_FORMAT_ERROR,
|
||||||
|
} srslte_pucch_format_t;
|
||||||
|
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
// Input configuration for this subframe
|
||||||
|
uint16_t rnti;
|
||||||
|
|
||||||
|
// UCI configuration
|
||||||
|
srslte_uci_cfg_t uci_cfg;
|
||||||
|
|
||||||
|
// Common configuration
|
||||||
|
uint32_t delta_pucch_shift;
|
||||||
|
uint32_t n_rb_2;
|
||||||
|
uint32_t N_cs;
|
||||||
|
uint32_t N_pucch_1;
|
||||||
|
bool group_hopping_en; // common pusch config
|
||||||
|
|
||||||
|
// Dedicated PUCCH configuration
|
||||||
|
uint32_t I_sr;
|
||||||
|
bool sr_configured;
|
||||||
|
uint32_t n_pucch_1[4]; // 4 n_pucch resources specified by RRC
|
||||||
|
uint32_t n_pucch_2;
|
||||||
|
uint32_t n_pucch_sr;
|
||||||
|
bool simul_cqi_ack;
|
||||||
|
bool tdd_ack_bundle; // if false, multiplex
|
||||||
|
bool sps_enabled;
|
||||||
|
uint32_t tpc_for_pucch;
|
||||||
|
|
||||||
|
// Release 10 CA specific
|
||||||
|
srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode;
|
||||||
|
uint32_t n1_pucch_an_cs[SRSLTE_PUCCH_SIZE_AN_CS][SRSLTE_PUCCH_NOF_AN_CS];
|
||||||
|
uint32_t n3_pucch_an_list[SRSLTE_PUCCH_SIZE_AN_CS];
|
||||||
|
|
||||||
|
// Other configuration
|
||||||
|
float threshold_format1;
|
||||||
|
float threshold_data_valid_format1a;
|
||||||
|
float threshold_data_valid_format2;
|
||||||
|
|
||||||
|
// PUCCH configuration generated during a call to encode/decode
|
||||||
|
srslte_pucch_format_t format;
|
||||||
|
uint32_t n_pucch;
|
||||||
|
uint8_t pucch2_drs_bits[SRSLTE_PUCCH2_MAX_DMRS_BITS];
|
||||||
|
|
||||||
|
} srslte_pucch_cfg_t;
|
||||||
|
|
||||||
|
#endif // SRSLTE_PUCCH_CFG_H
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* File: ra_dl.h
|
||||||
|
*
|
||||||
|
* Description: Implements Resource allocation Procedures for DL defined in Section 7
|
||||||
|
*
|
||||||
|
* Reference: 3GPP TS 36.213 version 10.0.1 Release 10
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_RA_DL_H
|
||||||
|
#define SRSLTE_RA_DL_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "srslte/config.h"
|
||||||
|
#include "srslte/phy/common/phy_common.h"
|
||||||
|
#include "srslte/phy/phch/dci.h"
|
||||||
|
#include "srslte/phy/phch/pdsch_cfg.h"
|
||||||
|
#include "srslte/phy/phch/ra.h"
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
* Structures used for Downlink Resource Allocation
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
/** Functions to generate a grant from a received DCI */
|
||||||
|
SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_cell_t* cell,
|
||||||
|
srslte_dl_sf_cfg_t* sf,
|
||||||
|
srslte_tm_t tm,
|
||||||
|
srslte_dci_dl_t* dci,
|
||||||
|
srslte_pdsch_grant_t* grant);
|
||||||
|
|
||||||
|
SRSLTE_API int srslte_ra_dl_grant_to_grant_prb_allocation(srslte_dci_dl_t* dci,
|
||||||
|
srslte_pdsch_grant_t* grant,
|
||||||
|
uint32_t nof_prb);
|
||||||
|
|
||||||
|
/** Functions used by the eNodeB scheduler */
|
||||||
|
SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t* cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols);
|
||||||
|
|
||||||
|
SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant);
|
||||||
|
|
||||||
|
/** Others */
|
||||||
|
SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_tb_t* tb, int last_tbs, uint32_t nprb);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_ra_dl_compute_nof_re(srslte_cell_t* cell, srslte_dl_sf_cfg_t* sf, srslte_pdsch_grant_t* grant);
|
||||||
|
|
||||||
|
SRSLTE_API uint32_t srslte_ra_dl_info(srslte_pdsch_grant_t* grant, char* info_str, uint32_t len);
|
||||||
|
|
||||||
|
#endif // SRSLTE_RA_DL_H
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* File: ra_ul.h
|
||||||
|
*
|
||||||
|
* Description: Implements Resource allocation Procedures for UL defined in Sections 8
|
||||||
|
*
|
||||||
|
* Reference: 3GPP TS 36.213 version 10.0.1 Release 10
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_RA_UL_H
|
||||||
|
#define SRSLTE_RA_UL_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "srslte/config.h"
|
||||||
|
#include "srslte/phy/common/phy_common.h"
|
||||||
|
#include "srslte/phy/phch/dci.h"
|
||||||
|
#include "srslte/phy/phch/pusch_cfg.h"
|
||||||
|
|
||||||
|
// Structure for PUSCH frequency hopping procedure
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
bool initialized;
|
||||||
|
srslte_cell_t cell;
|
||||||
|
srslte_sequence_t seq_type2_fo;
|
||||||
|
} srslte_ra_ul_pusch_hopping_t;
|
||||||
|
|
||||||
|
SRSLTE_API int srslte_ra_ul_pusch_hopping_init(srslte_ra_ul_pusch_hopping_t* q, srslte_cell_t cell);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_ra_ul_pusch_hopping_free(srslte_ra_ul_pusch_hopping_t* q);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_ra_ul_pusch_hopping(srslte_ra_ul_pusch_hopping_t* q,
|
||||||
|
srslte_ul_sf_cfg_t* sf,
|
||||||
|
srslte_pusch_hopping_cfg_t* hopping_cfg,
|
||||||
|
srslte_pusch_grant_t* grant);
|
||||||
|
|
||||||
|
/** Functions to generate a grant from a received DCI */
|
||||||
|
SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_cell_t* cell,
|
||||||
|
srslte_ul_sf_cfg_t* sf,
|
||||||
|
srslte_pusch_hopping_cfg_t* hopping_cfg,
|
||||||
|
srslte_dci_ul_t* dci,
|
||||||
|
srslte_pusch_grant_t* grant);
|
||||||
|
|
||||||
|
/** Others */
|
||||||
|
SRSLTE_API uint32_t srslte_ra_ul_info(srslte_pusch_grant_t* grant, char* info_str, uint32_t len);
|
||||||
|
|
||||||
|
#endif // SRSLTE_RA_UL_H
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UCI_CFG_H
|
||||||
|
#define SRSLTE_UCI_CFG_H
|
||||||
|
|
||||||
|
#include "srslte/phy/phch/cqi.h"
|
||||||
|
|
||||||
|
#define SRSLTE_UCI_MAX_ACK_BITS 10
|
||||||
|
#define SRSLTE_UCI_MAX_M 9
|
||||||
|
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
uint8_t ack_value[SRSLTE_UCI_MAX_ACK_BITS];
|
||||||
|
bool valid;
|
||||||
|
} srslte_uci_value_ack_t;
|
||||||
|
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
bool pending_tb[SRSLTE_MAX_CODEWORDS];
|
||||||
|
uint32_t nof_acks;
|
||||||
|
uint32_t ncce[SRSLTE_UCI_MAX_M];
|
||||||
|
uint32_t N_bundle;
|
||||||
|
uint32_t tdd_ack_M;
|
||||||
|
uint32_t tdd_ack_m;
|
||||||
|
bool tdd_is_bundling;
|
||||||
|
bool has_scell_ack;
|
||||||
|
} srslte_uci_cfg_ack_t;
|
||||||
|
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
srslte_uci_cfg_ack_t ack;
|
||||||
|
srslte_cqi_cfg_t cqi;
|
||||||
|
bool is_scheduling_request_tti;
|
||||||
|
} srslte_uci_cfg_t;
|
||||||
|
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
bool scheduling_request;
|
||||||
|
srslte_cqi_value_t cqi;
|
||||||
|
srslte_uci_value_ack_t ack;
|
||||||
|
uint8_t ri; // Only 1-bit supported for RI
|
||||||
|
} srslte_uci_value_t;
|
||||||
|
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
srslte_uci_cfg_t cfg;
|
||||||
|
srslte_uci_value_t value;
|
||||||
|
} srslte_uci_data_t;
|
||||||
|
|
||||||
|
typedef enum { UCI_BIT_0 = 0, UCI_BIT_1 = 1, UCI_BIT_REPETITION = 2, UCI_BIT_PLACEHOLDER = 3 } srslte_uci_bit_type_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t position;
|
||||||
|
srslte_uci_bit_type_t type;
|
||||||
|
} srslte_uci_bit_t;
|
||||||
|
|
||||||
|
#endif // SRSLTE_UCI_CFG_H
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2019 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "srslte/phy/common/phy_common.h"
|
||||||
|
#include "srslte/phy/common/timestamp.h"
|
||||||
|
#include "srslte/phy/rf/rf.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SRSLTE_RADIO_SYNC_H
|
||||||
|
#define SRSLTE_RADIO_SYNC_H
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
/* Interface to the RF frontend.
|
||||||
|
*/
|
||||||
|
class radio_sync
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void* thread_args;
|
||||||
|
|
||||||
|
public:
|
||||||
|
radio_sync();
|
||||||
|
bool init(srslte_rf_t* dev);
|
||||||
|
void issue_sync();
|
||||||
|
void issue_rx(cf_t* data[SRSLTE_MAX_PORTS],
|
||||||
|
uint32_t nsamples,
|
||||||
|
srslte_timestamp_t* timestamp,
|
||||||
|
bool start_streaming = false);
|
||||||
|
int wait();
|
||||||
|
~radio_sync();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_RADIO_SYNC_H
|
@ -1,159 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \section COPYRIGHT
|
|
||||||
*
|
|
||||||
* Copyright 2013-2015 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* \section LICENSE
|
|
||||||
*
|
|
||||||
* This file is part of the srsLTE library.
|
|
||||||
*
|
|
||||||
* srsLTE is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* srsLTE is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* A copy of the GNU Affero General Public License can be found in
|
|
||||||
* the LICENSE file in the top-level directory of this distribution
|
|
||||||
* and at http://www.gnu.org/licenses/.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "srslte/srslte.h"
|
|
||||||
#include "srslte/mex/mexutils.h"
|
|
||||||
|
|
||||||
|
|
||||||
/** MEX function to be called from MATLAB to test the channel estimator
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ENBCFG prhs[0]
|
|
||||||
#define INPUT prhs[1]
|
|
||||||
#define NOF_INPUTS 2
|
|
||||||
|
|
||||||
void help()
|
|
||||||
{
|
|
||||||
mexErrMsgTxt
|
|
||||||
("[estChannel, noiseEst, eq_output] = srslte_chest_dl(enb, inputSignal, [w_coeff])\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the gateway function */
|
|
||||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|
||||||
{
|
|
||||||
|
|
||||||
int i;
|
|
||||||
srslte_cell_t cell;
|
|
||||||
srslte_chest_dl_t chest;
|
|
||||||
|
|
||||||
cf_t *input_signal = NULL, *output_signal = NULL, *tmp_x[SRSLTE_MAX_LAYERS];
|
|
||||||
cf_t *ce[SRSLTE_MAX_PORTS];
|
|
||||||
|
|
||||||
for (int i=0;i<SRSLTE_MAX_LAYERS;i++) {
|
|
||||||
tmp_x[i] = NULL;
|
|
||||||
}
|
|
||||||
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
|
|
||||||
ce[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nrhs < NOF_INPUTS) {
|
|
||||||
help();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mexutils_read_cell(ENBCFG, &cell)) {
|
|
||||||
help();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t sf_idx=0;
|
|
||||||
if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &sf_idx)) {
|
|
||||||
help();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srslte_chest_dl_init(&chest, cell)) {
|
|
||||||
mexErrMsgTxt("Error initiating channel estimator\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Allocate input buffers */
|
|
||||||
int nof_re = 2*SRSLTE_CP_NSYMB(cell.cp)*cell.nof_prb*SRSLTE_NRE;
|
|
||||||
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
|
|
||||||
ce[i] = srslte_vec_malloc(nof_re * sizeof(cf_t));
|
|
||||||
}
|
|
||||||
for (i=0;i<SRSLTE_MAX_LAYERS;i++) {
|
|
||||||
tmp_x[i] = srslte_vec_malloc(nof_re * sizeof(cf_t));
|
|
||||||
}
|
|
||||||
output_signal = srslte_vec_malloc(nof_re * sizeof(cf_t));
|
|
||||||
|
|
||||||
// Read input signal
|
|
||||||
int insignal_len = mexutils_read_cf(INPUT, &input_signal);
|
|
||||||
if (insignal_len < 0) {
|
|
||||||
mexErrMsgTxt("Error reading input signal\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read optional value smooth filter coefficient
|
|
||||||
if (nrhs > NOF_INPUTS) {
|
|
||||||
float w = (float) mxGetScalar(prhs[NOF_INPUTS]);
|
|
||||||
srslte_chest_dl_set_smooth_filter3_coeff(&chest, w);
|
|
||||||
} else {
|
|
||||||
srslte_chest_dl_set_smooth_filter(&chest, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform channel estimation
|
|
||||||
if (srslte_chest_dl_estimate(&chest, input_signal, ce, sf_idx)) {
|
|
||||||
mexErrMsgTxt("Error running channel estimator\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get noise power estimation
|
|
||||||
float noise_power = srslte_chest_dl_get_noise_estimate(&chest);
|
|
||||||
|
|
||||||
// Perform channel equalization
|
|
||||||
if (cell.nof_ports == 1) {
|
|
||||||
srslte_predecoding_single(input_signal, ce[0], output_signal, nof_re, noise_power);
|
|
||||||
} else {
|
|
||||||
srslte_predecoding_diversity(input_signal, ce, tmp_x, cell.nof_ports, nof_re);
|
|
||||||
srslte_layerdemap_diversity(tmp_x, output_signal, cell.nof_ports, nof_re/cell.nof_ports);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write output values */
|
|
||||||
if (nlhs >= 1) {
|
|
||||||
mexutils_write_cf(ce[0], &plhs[0], mxGetM(INPUT), mxGetN(INPUT));
|
|
||||||
}
|
|
||||||
if (nlhs >= 2) {
|
|
||||||
plhs[1] = mxCreateLogicalScalar(noise_power);
|
|
||||||
}
|
|
||||||
if (nlhs >= 3) {
|
|
||||||
mexutils_write_cf(output_signal, &plhs[2], mxGetM(INPUT), mxGetN(INPUT));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free all memory
|
|
||||||
srslte_chest_dl_free(&chest);
|
|
||||||
|
|
||||||
for (i=0;i<SRSLTE_MAX_LAYERS;i++) {
|
|
||||||
if (tmp_x[i]) {
|
|
||||||
free(tmp_x[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
|
|
||||||
if (ce[i]) {
|
|
||||||
free(ce[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (input_signal) {
|
|
||||||
free(input_signal);
|
|
||||||
}
|
|
||||||
if (output_signal) {
|
|
||||||
free(output_signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
Binary file not shown.
@ -1,181 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \section COPYRIGHT
|
|
||||||
*
|
|
||||||
* Copyright 2013-2015 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* \section LICENSE
|
|
||||||
*
|
|
||||||
* This file is part of the srsLTE library.
|
|
||||||
*
|
|
||||||
* srsLTE is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* srsLTE is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* A copy of the GNU Affero General Public License can be found in
|
|
||||||
* the LICENSE file in the top-level directory of this distribution
|
|
||||||
* and at http://www.gnu.org/licenses/.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "srslte/srslte.h"
|
|
||||||
#include "srslte/mex/mexutils.h"
|
|
||||||
|
|
||||||
|
|
||||||
/** MEX function to be called from MATLAB to test the channel estimator
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define UECFG prhs[0]
|
|
||||||
#define PUSCHCFG prhs[1]
|
|
||||||
#define INPUT prhs[2]
|
|
||||||
#define NOF_INPUTS 3
|
|
||||||
|
|
||||||
void help()
|
|
||||||
{
|
|
||||||
mexErrMsgTxt
|
|
||||||
("[estChannel, noiseEst, eq_output] = srslte_chest_ul(ue_cfg, pusch_cfg, inputSignal, [w_coeff])\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the gateway function */
|
|
||||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|
||||||
{
|
|
||||||
|
|
||||||
srslte_cell_t cell;
|
|
||||||
srslte_chest_ul_t chest;
|
|
||||||
|
|
||||||
cf_t *input_signal = NULL, *output_signal = NULL;
|
|
||||||
cf_t *ce = NULL;
|
|
||||||
|
|
||||||
if (nrhs < NOF_INPUTS) {
|
|
||||||
help();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
|
|
||||||
mexErrMsgTxt("Field NCellID not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) {
|
|
||||||
mexErrMsgTxt("Field NCellID not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cell.cp = SRSLTE_CP_NORM;
|
|
||||||
cell.nof_ports = 1;
|
|
||||||
|
|
||||||
uint32_t sf_idx=0;
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
|
|
||||||
help();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
|
|
||||||
pusch_cfg.group_hopping_en = false;
|
|
||||||
pusch_cfg.sequence_hopping_en = false;
|
|
||||||
char *tmp = mexutils_get_char_struct(UECFG, "Hopping");
|
|
||||||
if (tmp) {
|
|
||||||
if (!strcmp(tmp, "Group")) {
|
|
||||||
pusch_cfg.group_hopping_en = true;
|
|
||||||
} else if (!strcmp(tmp, "Sequence")) {
|
|
||||||
pusch_cfg.sequence_hopping_en = true;
|
|
||||||
}
|
|
||||||
mxFree(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "SeqGroup", &pusch_cfg.delta_ss)) {
|
|
||||||
pusch_cfg.delta_ss = 0;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "CyclicShift", &pusch_cfg.cyclic_shift)) {
|
|
||||||
pusch_cfg.cyclic_shift = 0;
|
|
||||||
}
|
|
||||||
float *prbset;
|
|
||||||
mxArray *p;
|
|
||||||
p = mxGetField(PUSCHCFG, 0, "PRBSet");
|
|
||||||
if (!p) {
|
|
||||||
mexErrMsgTxt("Error field PRBSet not found in PUSCH config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t nof_prb = mexutils_read_f(p, &prbset);
|
|
||||||
uint32_t n_prb[2];
|
|
||||||
n_prb[0] = prbset[0];
|
|
||||||
n_prb[1] = prbset[0];
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t cyclic_shift_for_dmrs = 0;
|
|
||||||
if (mexutils_read_uint32_struct(PUSCHCFG, "DynCyclicShift", &cyclic_shift_for_dmrs)) {
|
|
||||||
cyclic_shift_for_dmrs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srslte_chest_ul_init(&chest, cell)) {
|
|
||||||
mexErrMsgTxt("Error initiating channel estimator\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
srslte_chest_ul_set_cfg(&chest, &pusch_cfg, NULL, NULL);
|
|
||||||
|
|
||||||
/** Allocate input buffers */
|
|
||||||
int nof_re = 2*SRSLTE_CP_NSYMB(cell.cp)*cell.nof_prb*SRSLTE_NRE;
|
|
||||||
ce = srslte_vec_malloc(nof_re * sizeof(cf_t));
|
|
||||||
output_signal = srslte_vec_malloc(nof_re * sizeof(cf_t));
|
|
||||||
|
|
||||||
// Read input signal
|
|
||||||
int insignal_len = mexutils_read_cf(INPUT, &input_signal);
|
|
||||||
if (insignal_len < 0) {
|
|
||||||
mexErrMsgTxt("Error reading input signal\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read optional value smooth filter coefficient
|
|
||||||
if (nrhs > NOF_INPUTS) {
|
|
||||||
float w = (float) mxGetScalar(prhs[NOF_INPUTS]);
|
|
||||||
srslte_chest_ul_set_smooth_filter3_coeff(&chest, w);
|
|
||||||
} else {
|
|
||||||
srslte_chest_ul_set_smooth_filter(&chest, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform channel estimation
|
|
||||||
if (srslte_chest_ul_estimate(&chest, input_signal, ce, nof_prb, sf_idx, cyclic_shift_for_dmrs, n_prb)) {
|
|
||||||
mexErrMsgTxt("Error running channel estimator\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get noise power estimation
|
|
||||||
float noise_power = srslte_chest_ul_get_noise_estimate(&chest);
|
|
||||||
|
|
||||||
// Perform channel equalization
|
|
||||||
srslte_predecoding_single(input_signal, ce, output_signal, nof_re, noise_power);
|
|
||||||
|
|
||||||
/* Write output values */
|
|
||||||
if (nlhs >= 1) {
|
|
||||||
mexutils_write_cf(ce, &plhs[0], mxGetM(INPUT), mxGetN(INPUT));
|
|
||||||
}
|
|
||||||
if (nlhs >= 2) {
|
|
||||||
plhs[1] = mxCreateDoubleScalar(noise_power);
|
|
||||||
}
|
|
||||||
if (nlhs >= 3) {
|
|
||||||
mexutils_write_cf(output_signal, &plhs[2], mxGetM(INPUT), mxGetN(INPUT));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free all memory
|
|
||||||
srslte_chest_ul_free(&chest);
|
|
||||||
|
|
||||||
if (ce) {
|
|
||||||
free(ce);
|
|
||||||
}
|
|
||||||
if (input_signal) {
|
|
||||||
free(input_signal);
|
|
||||||
}
|
|
||||||
if (output_signal) {
|
|
||||||
free(output_signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \section COPYRIGHT
|
|
||||||
*
|
|
||||||
* Copyright 2013-2015 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* \section LICENSE
|
|
||||||
*
|
|
||||||
* This file is part of the srsLTE library.
|
|
||||||
*
|
|
||||||
* srsLTE is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* srsLTE is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* A copy of the GNU Affero General Public License can be found in
|
|
||||||
* the LICENSE file in the top-level directory of this distribution
|
|
||||||
* and at http://www.gnu.org/licenses/.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "srslte/srslte.h"
|
|
||||||
#include "srslte/mex/mexutils.h"
|
|
||||||
|
|
||||||
/** MEX function to be called from MATLAB to test the channel estimator
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define UECFG prhs[0]
|
|
||||||
#define PUSCHCFG prhs[1]
|
|
||||||
#define NOF_INPUTS 2
|
|
||||||
|
|
||||||
void help()
|
|
||||||
{
|
|
||||||
mexErrMsgTxt
|
|
||||||
("[seq] = srslte_refsignal_pusch(ueConfig, puschConfig)\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int indices[2048];
|
|
||||||
|
|
||||||
/* the gateway function */
|
|
||||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|
||||||
{
|
|
||||||
srslte_cell_t cell;
|
|
||||||
srslte_refsignal_ul_t refs;
|
|
||||||
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
|
|
||||||
uint32_t sf_idx;
|
|
||||||
|
|
||||||
if (nrhs != NOF_INPUTS) {
|
|
||||||
help();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
|
|
||||||
mexErrMsgTxt("Field NCellID not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) {
|
|
||||||
mexErrMsgTxt("Field NCellID not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cell.cp = SRSLTE_CP_NORM;
|
|
||||||
cell.nof_ports = 1;
|
|
||||||
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
|
|
||||||
mexErrMsgTxt("Field NSubframe not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero(&pusch_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
|
|
||||||
|
|
||||||
|
|
||||||
pusch_cfg.group_hopping_en = false;
|
|
||||||
pusch_cfg.sequence_hopping_en = false;
|
|
||||||
char *tmp = mexutils_get_char_struct(UECFG, "Hopping");
|
|
||||||
if (tmp) {
|
|
||||||
if (!strcmp(tmp, "Group")) {
|
|
||||||
pusch_cfg.group_hopping_en = true;
|
|
||||||
} else if (!strcmp(tmp, "Sequence")) {
|
|
||||||
pusch_cfg.sequence_hopping_en = true;
|
|
||||||
}
|
|
||||||
mxFree(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "SeqGroup", &pusch_cfg.delta_ss)) {
|
|
||||||
pusch_cfg.delta_ss = 0;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "CyclicShift", &pusch_cfg.cyclic_shift)) {
|
|
||||||
pusch_cfg.cyclic_shift = 0;
|
|
||||||
}
|
|
||||||
float *prbset;
|
|
||||||
mxArray *p;
|
|
||||||
p = mxGetField(PUSCHCFG, 0, "PRBSet");
|
|
||||||
if (!p) {
|
|
||||||
mexErrMsgTxt("Error field PRBSet not found in PUSCH config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t nof_prb = mexutils_read_f(p, &prbset);
|
|
||||||
|
|
||||||
uint32_t cyclic_shift_for_dmrs = 0;
|
|
||||||
if (mexutils_read_uint32_struct(PUSCHCFG, "DynCyclicShift", &cyclic_shift_for_dmrs)) {
|
|
||||||
cyclic_shift_for_dmrs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srslte_refsignal_ul_init(&refs, cell)) {
|
|
||||||
mexErrMsgTxt("Error initiating srslte_refsignal_ul\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mexPrintf("nof_prb: %d, ",nof_prb);
|
|
||||||
mexPrintf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift);
|
|
||||||
mexPrintf("cyclic_shift_for_dmrs: %d, ", cyclic_shift_for_dmrs);
|
|
||||||
mexPrintf("delta_ss: %d, ",pusch_cfg.delta_ss);
|
|
||||||
|
|
||||||
cf_t *signal = srslte_vec_malloc(2*SRSLTE_NRE*nof_prb*sizeof(cf_t));
|
|
||||||
if (!signal) {
|
|
||||||
perror("malloc");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cf_t *sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t));
|
|
||||||
if (!sf_symbols) {
|
|
||||||
perror("malloc");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t));
|
|
||||||
|
|
||||||
srslte_refsignal_ul_set_cfg(&refs, &pusch_cfg, NULL, NULL);
|
|
||||||
|
|
||||||
//mexPrintf("Generating DRMS for ns=%d, nof_prb=%d\n", 2*sf_idx+i,pusch_cfg.nof_prb);
|
|
||||||
srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, cyclic_shift_for_dmrs, signal);
|
|
||||||
uint32_t n_prb[2];
|
|
||||||
n_prb[0] = prbset[0];
|
|
||||||
n_prb[1] = prbset[0];
|
|
||||||
srslte_refsignal_dmrs_pusch_put(&refs, signal, nof_prb, n_prb, sf_symbols);
|
|
||||||
if (nlhs >= 1) {
|
|
||||||
mexutils_write_cf(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
srslte_refsignal_ul_free(&refs);
|
|
||||||
free(signal);
|
|
||||||
free(prbset);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
@ -1,165 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \section COPYRIGHT
|
|
||||||
*
|
|
||||||
* Copyright 2013-2015 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* \section LICENSE
|
|
||||||
*
|
|
||||||
* This file is part of the srsLTE library.
|
|
||||||
*
|
|
||||||
* srsLTE is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* srsLTE is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* A copy of the GNU Affero General Public License can be found in
|
|
||||||
* the LICENSE file in the top-level directory of this distribution
|
|
||||||
* and at http://www.gnu.org/licenses/.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "srslte/srslte.h"
|
|
||||||
#include "srslte/mex/mexutils.h"
|
|
||||||
|
|
||||||
/** MEX function to be called from MATLAB to test the channel estimator
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define UECFG prhs[0]
|
|
||||||
#define SRSCFG prhs[1]
|
|
||||||
#define NOF_INPUTS 2
|
|
||||||
|
|
||||||
void help()
|
|
||||||
{
|
|
||||||
mexErrMsgTxt
|
|
||||||
("[sym, subframe]=srslte_refsignal_srs(ue, chs)\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the gateway function */
|
|
||||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|
||||||
{
|
|
||||||
|
|
||||||
if (nrhs != NOF_INPUTS) {
|
|
||||||
help();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
srslte_cell_t cell;
|
|
||||||
bzero(&cell, sizeof(srslte_cell_t));
|
|
||||||
cell.nof_ports = 1;
|
|
||||||
cell.cp = SRSLTE_CP_NORM;
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
|
|
||||||
mexErrMsgTxt("Field NCellID not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) {
|
|
||||||
mexErrMsgTxt("Field NULRB not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t sf_idx = 0;
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
|
|
||||||
mexErrMsgTxt("Field NSubframe not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t nf = 0;
|
|
||||||
if (mexutils_read_uint32_struct(UECFG, "NFrame", &nf)) {
|
|
||||||
mexErrMsgTxt("Field NFrame not found in UE config\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t tti = nf*10+sf_idx;
|
|
||||||
|
|
||||||
srslte_refsignal_srs_cfg_t srs_cfg;
|
|
||||||
bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
|
|
||||||
|
|
||||||
if (mexutils_read_uint32_struct(SRSCFG, "BWConfig", &srs_cfg.bw_cfg)) {
|
|
||||||
mexErrMsgTxt("Field BWConfig not found in SRSCFG\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(SRSCFG, "BW", &srs_cfg.B)) {
|
|
||||||
mexErrMsgTxt("Field BW not found in SRSCFG\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(SRSCFG, "ConfigIdx", &srs_cfg.I_srs)) {
|
|
||||||
mexErrMsgTxt("Field ConfigIdx not found in SRSCFG\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(SRSCFG, "FreqPosition", &srs_cfg.n_rrc)) {
|
|
||||||
mexErrMsgTxt("Field FreqPosition not found in SRSCFG\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(SRSCFG, "HoppingBW", &srs_cfg.b_hop)) {
|
|
||||||
mexErrMsgTxt("Field HoppingBW not found in SRSCFG\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(SRSCFG, "TxComb", &srs_cfg.k_tc)) {
|
|
||||||
mexErrMsgTxt("Field TxComb not found in SRSCFG\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mexutils_read_uint32_struct(SRSCFG, "CyclicShift", &srs_cfg.n_srs)) {
|
|
||||||
mexErrMsgTxt("Field CyclicShift not found in SRSCFG\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bool group_hopping_en = false;
|
|
||||||
char *hop = mexutils_get_char_struct(UECFG, "Hopping");
|
|
||||||
if (hop) {
|
|
||||||
if (!strcmp(hop, "Group")) {
|
|
||||||
group_hopping_en = true;
|
|
||||||
}
|
|
||||||
mxFree(hop);
|
|
||||||
}
|
|
||||||
|
|
||||||
cf_t *r_srs = srslte_vec_malloc(sizeof(cf_t) * cell.nof_prb * 12);
|
|
||||||
if (!r_srs) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bzero(r_srs, cell.nof_prb * 12 * sizeof(cf_t));
|
|
||||||
|
|
||||||
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
|
||||||
if (!sf_symbols) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
|
||||||
|
|
||||||
srslte_refsignal_ul_t refsignal;
|
|
||||||
if (srslte_refsignal_ul_init(&refsignal, cell)) {
|
|
||||||
mexErrMsgTxt("Error initiating UL refsignal\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
|
|
||||||
pusch_cfg.group_hopping_en = group_hopping_en;
|
|
||||||
pusch_cfg.sequence_hopping_en = false;
|
|
||||||
srslte_refsignal_ul_set_cfg(&refsignal, &pusch_cfg, NULL, &srs_cfg);
|
|
||||||
|
|
||||||
if (srslte_refsignal_srs_gen(&refsignal, sf_idx, r_srs)) {
|
|
||||||
mexErrMsgTxt("Error generating SRS\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srslte_refsignal_srs_put(&refsignal, tti, r_srs, sf_symbols)) {
|
|
||||||
mexErrMsgTxt("Error allocating SRS\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nlhs >= 1) {
|
|
||||||
uint32_t M_sc = srslte_refsignal_srs_M_sc(&refsignal); ;
|
|
||||||
mexutils_write_cf(r_srs, &plhs[0], M_sc, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nlhs >= 2) {
|
|
||||||
mexutils_write_cf(sf_symbols, &plhs[1], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
srslte_refsignal_ul_free(&refsignal);
|
|
||||||
free(sf_symbols);
|
|
||||||
free(r_srs);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue