Added enb_ul

master
Ismael Gomez 9 years ago
parent 6d70d5cb94
commit b5eedf07af

@ -495,7 +495,7 @@ int main(int argc, char **argv) {
decode_pdsch = true; decode_pdsch = true;
} else { } else {
/* We are looking for SIB1 Blocks, search only in appropiate places */ /* We are looking for SIB1 Blocks, search only in appropiate places */
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%8)==0)) {
decode_pdsch = true; decode_pdsch = true;
} else { } else {
decode_pdsch = false; decode_pdsch = false;

@ -42,7 +42,7 @@
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/dft/ofdm.h" #include "srslte/dft/ofdm.h"
#include "srslte/ch_estimation/refsignal_ul.h" #include "srslte/ch_estimation/chest_ul.h"
#include "srslte/phch/prach.h" #include "srslte/phch/prach.h"
#include "srslte/phch/pusch.h" #include "srslte/phch/pusch.h"
#include "srslte/phch/pusch_cfg.h" #include "srslte/phch/pusch_cfg.h"
@ -56,14 +56,17 @@
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
cf_t *sf_symbols[SRSLTE_MAX_PORTS]; cf_t *sf_symbols;
cf_t *ce;
srslte_ofdm_t fft;
srslte_chest_ul_t chest;
srslte_ofdm_t fft;
srslte_pusch_t pusch; srslte_pusch_t pusch;
srslte_pucch_t pucch;
srslte_prach_t prach; srslte_prach_t prach;
srslte_refsignal_ul_t ul_refs; srslte_pusch_cfg_t pusch_cfg;
srslte_pusch_cfg_t pusch_cfg;
srslte_softbuffer_rx_t softbuffer; srslte_softbuffer_rx_t softbuffer;
} srslte_enb_ul_t; } srslte_enb_ul_t;
@ -72,30 +75,33 @@ typedef struct {
srslte_ra_ul_dci_t grant; srslte_ra_ul_dci_t grant;
uint32_t rnti_idx; uint32_t rnti_idx;
uint32_t rv_idx; uint32_t rv_idx;
uint32_t current_tx_nb;
uint8_t *data; uint8_t *data;
} srslte_enb_ul_pusch_t; } srslte_enb_ul_pusch_t;
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q, SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
srslte_cell_t cell, srslte_cell_t cell,
srslte_prach_cfg_t* prach_cfg,
uint32_t nof_rntis); uint32_t nof_rntis);
SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q); SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q);
SRSLTE_API void srslte_enb_ul_set_cfi(srslte_enb_ul_t *q,
uint32_t cfi);
SRSLTE_API void srslte_enb_ul_rx_signal(srslte_enb_ul_t *q,
cf_t *signal_buffer);
SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q,
uint32_t idx, uint32_t idx,
uint16_t rnti); uint16_t rnti);
SRSLTE_API int srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q,
uint32_t idx);
SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q,
cf_t *signal_buffer);
SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q,
srslte_ra_ul_dci_t *grant, srslte_ra_ul_grant_t *grant,
uint32_t rnti_idx, uint32_t rnti_idx,
uint32_t rv_idx, uint32_t rv_idx,
uint32_t current_tx_nb,
uint8_t *data, uint8_t *data,
uint32_t sf_idx); uint32_t sf_idx);
@ -104,8 +110,12 @@ SRSLTE_API int srslte_enb_ul_get_pusch_multi(srslte_enb_ul_t *q,
uint32_t nof_pusch, uint32_t nof_pusch,
uint32_t sf_idx); uint32_t sf_idx);
SRSLTE_API int srslte_enb_ul_get_prach(srslte_enb_ul_t *q, SRSLTE_API int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q,
uint32_t sf_idx); uint32_t tti,
uint32_t freq_offset,
cf_t *signal,
uint32_t *indices,
uint32_t *offsets);
#endif #endif

@ -41,7 +41,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "srslte/config.h" #include "srslte/config.h"
#include "srslte/dft/dft.h" #include "srslte/dft/dft.h"
#include "srslte/common/phy_common.h"
/** Generation and detection of RACH signals for uplink. /** Generation and detection of RACH signals for uplink.
@ -52,6 +52,7 @@
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
// Parameters from higher layers (extracted from SIB2) // Parameters from higher layers (extracted from SIB2)
uint32_t config_idx;
uint32_t f; // preamble format uint32_t f; // preamble format
uint32_t rsi; // rootSequenceIndex uint32_t rsi; // rootSequenceIndex
bool hs; // highSpeedFlag bool hs; // highSpeedFlag
@ -105,24 +106,36 @@ typedef enum SRSLTE_API {
SRSLTE_PRACH_SFN_ANY, SRSLTE_PRACH_SFN_ANY,
} srslte_prach_sfn_t; } srslte_prach_sfn_t;
typedef struct {
uint32_t config_idx;
uint32_t root_seq_idx;
uint32_t zero_corr_zone;
bool hs_flag;
} srslte_prach_cfg_t;
SRSLTE_API uint32_t srslte_prach_get_preamble_format(uint32_t config_idx); SRSLTE_API uint32_t srslte_prach_get_preamble_format(uint32_t config_idx);
SRSLTE_API srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx); SRSLTE_API srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx);
SRSLTE_API bool srslte_prach_send_tti(uint32_t config_idx, SRSLTE_API bool srslte_prach_tti_opportunity(srslte_prach_t *p,
uint32_t current_tti, uint32_t current_tti,
int allowed_subframe); int allowed_subframe);
SRSLTE_API void srslte_prach_sf_config(uint32_t config_idx, SRSLTE_API void srslte_prach_sf_config(uint32_t config_idx,
srslte_prach_sf_config_t *sf_config); srslte_prach_sf_config_t *sf_config);
SRSLTE_API int srslte_prach_init(srslte_prach_t *p, SRSLTE_API int srslte_prach_init(srslte_prach_t *p,
uint32_t N_ifft_ul, uint32_t N_ifft_ul,
uint32_t preamble_format, uint32_t config_idx,
uint32_t root_seq_index, uint32_t root_seq_index,
bool high_speed_flag, bool high_speed_flag,
uint32_t zero_corr_zone_config); uint32_t zero_corr_zone_config);
SRSLTE_API int srslte_prach_init_cfg(srslte_prach_t* p,
srslte_prach_cfg_t* cfg,
uint32_t nof_prb);
SRSLTE_API int srslte_prach_gen(srslte_prach_t *p, SRSLTE_API int srslte_prach_gen(srslte_prach_t *p,
uint32_t seq_index, uint32_t seq_index,
uint32_t freq_offset, uint32_t freq_offset,

@ -87,7 +87,12 @@ typedef struct SRSLTE_API {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq_type2_fo; srslte_sequence_t seq_type2_fo;
srslte_sch_t dl_sch; // This is to generate the scrambling seq for multiple CRNTIs
uint32_t nof_crnti;
srslte_sequence_t *seq_multi[SRSLTE_NSUBFRAMES_X_FRAME];
uint16_t *rnti_multi;
srslte_sch_t ul_sch;
bool shortened; bool shortened;
}srslte_pusch_t; }srslte_pusch_t;
@ -111,6 +116,17 @@ SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q, SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q,
uint16_t rnti); uint16_t rnti);
SRSLTE_API int srslte_pusch_init_rnti_multi(srslte_pusch_t *q,
uint32_t nof_rntis);
SRSLTE_API int srslte_pusch_set_rnti_multi(srslte_pusch_t *q,
uint32_t idx,
uint16_t rnti);
SRSLTE_API uint16_t srslte_pusch_get_rnti_multi(srslte_pusch_t *q,
uint32_t idx);
SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q, SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q,
srslte_pusch_cfg_t *cfg, srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer, srslte_softbuffer_tx_t *softbuffer,
@ -156,6 +172,16 @@ SRSLTE_API int srslte_pusch_uci_decode(srslte_pusch_t *q,
uint8_t *data, uint8_t *data,
srslte_uci_data_t *uci_data); srslte_uci_data_t *uci_data);
SRSLTE_API int srslte_pusch_uci_decode_rnti_idx(srslte_pusch_t *q,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols,
cf_t *ce,
float noise_estimate,
uint32_t rnti_idx,
uint8_t *data,
srslte_uci_data_t *uci_data);
SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q); SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q);
SRSLTE_API uint32_t srslte_pusch_last_noi(srslte_pusch_t *q); SRSLTE_API uint32_t srslte_pusch_last_noi(srslte_pusch_t *q);

@ -37,16 +37,6 @@
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define MAX_CANDIDATES 64
/*
static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also
const static uint32_t nof_ue_formats = 2;
static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1C};
const static uint32_t nof_common_formats = 2;
*/
int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell, uint32_t nof_rnti) int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell, uint32_t nof_rnti)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;

@ -0,0 +1,222 @@
/**
*
* \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 "srslte/enb/enb_ul.h"
#include <complex.h>
#include <math.h>
#include <string.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
#define CURRENT_SFLEN SRSLTE_SF_LEN(CURRENT_FFTSIZE)
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define MAX_CANDIDATES 64
int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
srslte_prach_cfg_t *prach_cfg, uint32_t nof_rnti)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_enb_ul_t));
q->cell = cell;
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
srslte_ofdm_set_normalize(&q->fft, true);
srslte_ofdm_set_freq_shift(&q->fft, 0.5);
if (srslte_pucch_init(&q->pucch, q->cell)) {
fprintf(stderr, "Error creating PUCCH object\n");
goto clean_exit;
}
if (srslte_pusch_init(&q->pusch, q->cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
if (srslte_pusch_init_rnti_multi(&q->pusch, nof_rnti)) {
fprintf(stderr, "Error initiating multiple RNTIs in PUSCH\n");
goto clean_exit;
}
if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating PRACH\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;
}
if (srslte_chest_ul_init(&q->chest, cell)) {
fprintf(stderr, "Error initiating channel estimator\n");
goto clean_exit;
}
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->ce = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->ce) {
perror("malloc");
goto clean_exit;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
clean_exit:
if (ret == SRSLTE_ERROR) {
srslte_enb_ul_free(q);
}
return ret;
}
void srslte_enb_ul_free(srslte_enb_ul_t *q)
{
if (q) {
srslte_prach_free(&q->prach);
srslte_ofdm_rx_free(&q->fft);
srslte_pucch_free(&q->pucch);
srslte_pusch_free(&q->pusch);
srslte_softbuffer_rx_free(&q->softbuffer);
srslte_chest_ul_free(&q->chest);
if (q->sf_symbols) {
free(q->sf_symbols);
}
if (q->ce) {
free(q->ce);
}
bzero(q, sizeof(srslte_enb_ul_t));
}
}
int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint32_t idx, uint16_t rnti)
{
return srslte_pusch_set_rnti_multi(&q->pusch, idx, rnti);
}
int srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, uint32_t idx)
{
return srslte_pusch_set_rnti_multi(&q->pusch, idx, 0);
}
void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer)
{
srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols);
}
int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant,
uint32_t rnti_idx, uint32_t rv_idx, uint32_t current_tx_nb,
uint8_t *data, uint32_t sf_idx)
{
if (srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, NULL, NULL, NULL, sf_idx, rv_idx, current_tx_nb)) {
fprintf(stderr, "Error configuring PDSCH\n");
return SRSLTE_ERROR;
}
uint32_t cyclic_shift_for_dmrs = 0;
srslte_chest_ul_estimate(&q->chest, q->sf_symbols, q->ce, grant->L_prb, sf_idx, cyclic_shift_for_dmrs, grant->n_prb);
float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest);
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return srslte_pusch_uci_decode_rnti_idx(&q->pusch, &q->pusch_cfg,
&q->softbuffer, q->sf_symbols,
q->ce, noise_power,
rnti_idx, data,
&uci_data);
}
int srslte_enb_ul_get_pusch_multi(srslte_enb_ul_t *q, srslte_enb_ul_pusch_t *grants,
uint32_t nof_pusch, uint32_t tti)
{
uint32_t n_rb_ho = 0;
for (int i=0;i<nof_pusch;i++) {
srslte_ra_ul_grant_t phy_grant;
srslte_ra_ul_dci_to_grant(&grants[i].grant, q->cell.nof_prb, n_rb_ho, &phy_grant, tti%8);
if (srslte_enb_ul_get_pusch(q, &phy_grant, grants[i].rnti_idx, grants[i].rv_idx,
grants[i].current_tx_nb, grants[i].data, tti%10) < 0)
{
fprintf(stderr, "Error getting PUSCH\n");
return SRSLTE_ERROR;
}
}
return SRSLTE_SUCCESS;
}
int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q, uint32_t tti,
uint32_t freq_offset, cf_t *signal,
uint32_t *indices, uint32_t *offsets)
{
uint32_t nof_detected_prach = 0;
// consider the number of subframes the transmission must be anticipated
if (srslte_prach_tti_opportunity(&q->prach, tti, -1))
{
if (srslte_prach_detect_offset(&q->prach,
freq_offset,
&signal[q->prach.N_cp],
SRSLTE_SF_LEN_PRB(q->cell.nof_prb),
indices,
offsets,
&nof_detected_prach))
{
fprintf(stderr, "Error detecting PRACH\n");
return SRSLTE_ERROR;
}
}
return (int) nof_detected_prach;
}

@ -189,7 +189,9 @@ srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx) {
/* Returns true if current_tti is a valid opportunity for PRACH transmission and the is an allowed subframe, /* Returns true if current_tti is a valid opportunity for PRACH transmission and the is an allowed subframe,
* or allowed_subframe == -1 * or allowed_subframe == -1
*/ */
bool srslte_prach_send_tti(uint32_t config_idx, uint32_t current_tti, int allowed_subframe) { bool srslte_prach_tti_opportunity(srslte_prach_t *p, uint32_t current_tti, int allowed_subframe)
{
uint32_t config_idx = p->config_idx;
// Get SFN and sf_idx from the PRACH configuration index // Get SFN and sf_idx from the PRACH configuration index
srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn(config_idx); srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn(config_idx);
@ -319,9 +321,19 @@ int srslte_prach_gen_seqs(srslte_prach_t *p)
return 0; return 0;
} }
int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb)
{
return srslte_prach_init(p,
srslte_symbol_sz(nof_prb),
cfg->config_idx,
cfg->root_seq_idx,
cfg->hs_flag,
cfg->zero_corr_zone);
}
int srslte_prach_init(srslte_prach_t *p, int srslte_prach_init(srslte_prach_t *p,
uint32_t N_ifft_ul, uint32_t N_ifft_ul,
uint32_t preamble_format, uint32_t config_idx,
uint32_t root_seq_index, uint32_t root_seq_index,
bool high_speed_flag, bool high_speed_flag,
uint32_t zero_corr_zone_config) uint32_t zero_corr_zone_config)
@ -329,11 +341,12 @@ int srslte_prach_init(srslte_prach_t *p,
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
if(p != NULL && if(p != NULL &&
N_ifft_ul < 2049 && N_ifft_ul < 2049 &&
preamble_format < 4 && // Currently supporting formats 0-3 config_idx < 16 &&
root_seq_index < MAX_ROOTS && root_seq_index < MAX_ROOTS &&
zero_corr_zone_config < 16) zero_corr_zone_config < 16)
{ {
uint32_t preamble_format = srslte_prach_get_preamble_format(config_idx);
p->config_idx = config_idx;
p->f = preamble_format; p->f = preamble_format;
p->rsi = root_seq_index; p->rsi = root_seq_index;
p->hs = high_speed_flag; p->hs = high_speed_flag;
@ -453,7 +466,9 @@ int srslte_prach_gen(srslte_prach_t *p,
uint32_t K = DELTA_F/DELTA_F_RA; uint32_t K = DELTA_F/DELTA_F_RA;
uint32_t begin = PHI + (K*k_0) + (K/2); uint32_t begin = PHI + (K*k_0) + (K/2);
DEBUG("N_zc: %d, N_cp: %d, N_seq: %d, N_ifft_prach=%d begin: %d\n", p->N_zc, p->N_cp, p->N_seq, p->N_ifft_prach, begin); DEBUG("N_zc: %d, N_cp: %d, N_seq: %d, N_ifft_prach=%d begin: %d\n",
p->N_zc, p->N_cp, p->N_seq, p->N_ifft_prach, begin);
// Map dft-precoded sequence to ifft bins // Map dft-precoded sequence to ifft bins
memset(p->ifft_in, 0, begin*sizeof(cf_t)); memset(p->ifft_in, 0, begin*sizeof(cf_t));
memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t)); memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t));
@ -503,6 +518,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
sig_len > 0 && sig_len > 0 &&
indices != NULL) indices != NULL)
{ {
if(sig_len < p->N_ifft_prach){ if(sig_len < p->N_ifft_prach){
fprintf(stderr, "srslte_prach_detect: Signal is not of length %d", p->N_ifft_prach); fprintf(stderr, "srslte_prach_detect: Signal is not of length %d", p->N_ifft_prach);
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
@ -541,6 +557,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
uint32_t n_wins = p->N_zc/winsize; uint32_t n_wins = p->N_zc/winsize;
float max_peak = 0; float max_peak = 0;
for(int j=0;j<n_wins;j++) { for(int j=0;j<n_wins;j++) {
uint32_t start = (p->N_zc-(j*p->N_cs))%p->N_zc; uint32_t start = (p->N_zc-(j*p->N_cs))%p->N_zc;
uint32_t end = start+winsize; uint32_t end = start+winsize;
@ -549,7 +566,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
} }
start += p->deadzone; start += p->deadzone;
p->peak_values[j] = 0; p->peak_values[j] = 0;
for(int k=start;k<end;k++){ for(int k=start;k<end;k++) {
if(p->corr[k] > p->peak_values[j]) { if(p->corr[k] > p->peak_values[j]) {
p->peak_values[j] = p->corr[k]; p->peak_values[j] = p->corr[k];
p->peak_offsets[j] = k-start; p->peak_offsets[j] = k-start;

@ -215,7 +215,7 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
goto clean; goto clean;
} }
srslte_sch_init(&q->dl_sch); srslte_sch_init(&q->ul_sch);
if (srslte_dft_precoding_init(&q->dft_precoding, cell.nof_prb)) { if (srslte_dft_precoding_init(&q->dft_precoding, cell.nof_prb)) {
fprintf(stderr, "Error initiating DFT transform precoding\n"); fprintf(stderr, "Error initiating DFT transform precoding\n");
@ -288,7 +288,7 @@ void srslte_pusch_free(srslte_pusch_t *q) {
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
srslte_modem_table_free(&q->mod[i]); srslte_modem_table_free(&q->mod[i]);
} }
srslte_sch_free(&q->dl_sch); srslte_sch_free(&q->ul_sch);
bzero(q, sizeof(srslte_pusch_t)); bzero(q, sizeof(srslte_pusch_t));
@ -398,6 +398,61 @@ int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) {
} }
/* Initializes the memory to support pre-calculation of multiple scrambling sequences */
int srslte_pusch_init_rnti_multi(srslte_pusch_t *q, uint32_t nof_rntis)
{
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
q->seq_multi[i] = malloc(sizeof(srslte_sequence_t)*nof_rntis);
if (!q->seq_multi[i]) {
perror("malloc");
return SRSLTE_ERROR;
}
}
q->rnti_multi = srslte_vec_malloc(sizeof(uint16_t)*nof_rntis);
if (!q->rnti_multi) {
perror("malloc");
return SRSLTE_ERROR;
}
bzero(q->rnti_multi, sizeof(uint16_t)*nof_rntis);
q->nof_crnti = nof_rntis;
return SRSLTE_SUCCESS;
}
int srslte_pusch_set_rnti_multi(srslte_pusch_t *q, uint32_t idx, uint16_t rnti)
{
if (idx < q->nof_crnti) {
if (q->rnti_multi[idx]) {
for (uint32_t i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
srslte_sequence_free(&q->seq_multi[i][idx]);
}
q->rnti_multi[idx] = 0;
}
q->rnti_multi[idx] = rnti;
q->rnti_is_set = true;
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
if (srslte_sequence_pusch(&q->seq_multi[i][idx], rnti, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
return SRSLTE_ERROR;
}
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
uint16_t srslte_pusch_get_rnti_multi(srslte_pusch_t *q, uint32_t idx)
{
if (idx < q->nof_crnti) {
return q->rnti_multi[idx];
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
int srslte_pusch_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, int srslte_pusch_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, uint16_t rnti, uint8_t *data, uint16_t rnti,
cf_t *sf_symbols) cf_t *sf_symbols)
@ -455,7 +510,7 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs
cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_symb, cfg->nbits.nof_bits, cfg->rv); cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_symb, cfg->nbits.nof_bits, cfg->rv);
bzero(q->q, cfg->nbits.nof_bits); bzero(q->q, cfg->nbits.nof_bits);
if (srslte_ulsch_uci_encode(&q->dl_sch, cfg, softbuffer, data, uci_data, q->g, q->q)) { if (srslte_ulsch_uci_encode(&q->ul_sch, cfg, softbuffer, data, uci_data, q->g, q->q)) {
fprintf(stderr, "Error encoding TB\n"); fprintf(stderr, "Error encoding TB\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -473,12 +528,12 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs
// Correct UCI placeholder/repetition bits // Correct UCI placeholder/repetition bits
uint8_t *d = q->q; uint8_t *d = q->q;
for (int i = 0; i < q->dl_sch.nof_ri_ack_bits; i++) { for (int i = 0; i < q->ul_sch.nof_ri_ack_bits; i++) {
if (q->dl_sch.ack_ri_bits[i].type == UCI_BIT_PLACEHOLDER) { if (q->ul_sch.ack_ri_bits[i].type == UCI_BIT_PLACEHOLDER) {
d[q->dl_sch.ack_ri_bits[i].position/8] |= (1<<(7-q->dl_sch.ack_ri_bits[i].position%8)); d[q->ul_sch.ack_ri_bits[i].position/8] |= (1<<(7-q->ul_sch.ack_ri_bits[i].position%8));
} else if (q->dl_sch.ack_ri_bits[i].type == UCI_BIT_REPETITION) { } else if (q->ul_sch.ack_ri_bits[i].type == UCI_BIT_REPETITION) {
if (q->dl_sch.ack_ri_bits[i].position > 1) { if (q->ul_sch.ack_ri_bits[i].position > 1) {
uint32_t p=q->dl_sch.ack_ri_bits[i].position; uint32_t p=q->ul_sch.ack_ri_bits[i].position;
uint8_t bit = d[(p-1)/8] & (1<<(7-(p-1)%8)); uint8_t bit = d[(p-1)/8] & (1<<(7-(p-1)%8));
if (bit) { if (bit) {
d[p/8] |= 1<<(7-p%8); d[p/8] |= 1<<(7-p%8);
@ -514,14 +569,12 @@ int srslte_pusch_decode(srslte_pusch_t *q,
return srslte_pusch_uci_decode(q, cfg, softbuffer, sf_symbols, ce, noise_estimate, data, &uci_data); return srslte_pusch_uci_decode(q, cfg, softbuffer, sf_symbols, ce, noise_estimate, data, &uci_data);
} }
int srslte_pusch_uci_decode_seq(srslte_pusch_t *q,
/** Decodes the PUSCH from the received symbols srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
*/ srslte_sequence_t *seq,
int srslte_pusch_uci_decode(srslte_pusch_t *q, cf_t *sf_symbols,
srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *ce, float noise_estimate,
cf_t *sf_symbols, uint8_t *data, srslte_uci_data_t *uci_data)
cf_t *ce, float noise_estimate,
uint8_t *data, srslte_uci_data_t *uci_data)
{ {
uint32_t n; uint32_t n;
@ -561,15 +614,15 @@ int srslte_pusch_uci_decode(srslte_pusch_t *q,
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re); srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re);
// Decode RI/HARQ bits before descrambling // Decode RI/HARQ bits before descrambling
if (srslte_ulsch_uci_decode_ri_ack(&q->dl_sch, cfg, softbuffer, q->q, q->seq[cfg->sf_idx].c, uci_data)) { if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, q->seq[cfg->sf_idx].c, uci_data)) {
fprintf(stderr, "Error decoding RI/HARQ bits\n"); fprintf(stderr, "Error decoding RI/HARQ bits\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
// Descrambling // Descrambling
srslte_scrambling_s_offset(&q->seq[cfg->sf_idx], q->q, 0, cfg->nbits.nof_bits); srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits);
return srslte_ulsch_uci_decode(&q->dl_sch, cfg, softbuffer, q->q, q->g, data, uci_data); return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data);
} else { } else {
fprintf(stderr, "Must call srslte_pusch_set_rnti() before calling srslte_pusch_decode()\n"); fprintf(stderr, "Must call srslte_pusch_set_rnti() before calling srslte_pusch_decode()\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -579,3 +632,36 @@ int srslte_pusch_uci_decode(srslte_pusch_t *q,
} }
} }
/** Decodes the PUSCH from the received symbols
*/
int srslte_pusch_uci_decode(srslte_pusch_t *q,
srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols,
cf_t *ce, float noise_estimate,
uint8_t *data, srslte_uci_data_t *uci_data)
{
return srslte_pusch_uci_decode_seq(q, cfg, softbuffer, &q->seq[cfg->sf_idx], sf_symbols, ce, noise_estimate, data, uci_data);
}
/** Decodes the PUSCH from the received symbols for a given RNTI index
*/
int srslte_pusch_uci_decode_rnti_idx(srslte_pusch_t *q,
srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols,
cf_t *ce, float noise_estimate,
uint32_t rnti_idx,
uint8_t *data, srslte_uci_data_t *uci_data)
{
if (rnti_idx < q->nof_crnti) {
if (q->rnti_multi[rnti_idx]) {
return srslte_pusch_uci_decode_seq(q, cfg, softbuffer, &q->seq_multi[cfg->sf_idx][rnti_idx], sf_symbols, ce, noise_estimate, data, uci_data);
} else {
fprintf(stderr, "Error RNTI idx %d not set\n", rnti_idx);
return SRSLTE_ERROR;
}
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}

@ -40,13 +40,13 @@
uint32_t N_ifft_ul = 1536; uint32_t N_ifft_ul = 1536;
uint32_t preamble_format = 0; uint32_t config_idx = 3;
uint32_t root_seq_idx = 0; uint32_t root_seq_idx = 0;
uint32_t zero_corr_zone = 1; uint32_t zero_corr_zone = 15;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s\n", prog); printf("Usage: %s\n", prog);
printf("\t-N Uplink IFFT size [Default 128]\n"); printf("\t-N Uplink IFFT size [Default %d]\n", N_ifft_ul);
printf("\t-f Preamble format [Default 0]\n"); printf("\t-f Preamble format [Default 0]\n");
printf("\t-r Root sequence index [Default 0]\n"); printf("\t-r Root sequence index [Default 0]\n");
printf("\t-z Zero correlation zone config [Default 1]\n"); printf("\t-z Zero correlation zone config [Default 1]\n");
@ -60,7 +60,7 @@ void parse_args(int argc, char **argv) {
N_ifft_ul = atoi(argv[optind]); N_ifft_ul = atoi(argv[optind]);
break; break;
case 'f': case 'f':
preamble_format = atoi(argv[optind]); config_idx = atoi(argv[optind]);
break; break;
case 'r': case 'r':
root_seq_idx = atoi(argv[optind]); root_seq_idx = atoi(argv[optind]);
@ -87,7 +87,7 @@ int main(int argc, char **argv) {
srslte_prach_init(p, srslte_prach_init(p,
N_ifft_ul, N_ifft_ul,
preamble_format, config_idx,
root_seq_idx, root_seq_idx,
high_speed_flag, high_speed_flag,
zero_corr_zone); zero_corr_zone);
@ -108,11 +108,13 @@ int main(int argc, char **argv) {
preamble); preamble);
uint32_t prach_len = p->N_seq; uint32_t prach_len = p->N_seq;
if(preamble_format == 2 || preamble_format == 3)
prach_len /= 2;
srslte_prach_detect(p, 0, &preamble[p->N_cp], prach_len, indices, &n_indices);
struct timeval t[3];
gettimeofday(&t[1], NULL);
srslte_prach_detect(p, frequency_offset, &preamble[p->N_cp], prach_len, indices, &n_indices);
gettimeofday(&t[2], NULL);
get_time_interval(t);
printf("texec=%d us\n", t[0].tv_usec);
if(n_indices != 1 || indices[0] != seq_index) if(n_indices != 1 || indices[0] != seq_index)
return -1; return -1;
} }

@ -50,7 +50,7 @@ int rv_seq[4] = {0, 2, 3, 1};
/* the gateway function */ /* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ {
srslte_ofdm_t ofdm_tx; srslte_ofdm_t ofdm_rx;
srslte_pusch_t pusch; srslte_pusch_t pusch;
srslte_chest_ul_t chest; srslte_chest_ul_t chest;
cf_t *input_fft; cf_t *input_fft;
@ -88,12 +88,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
if (srslte_ofdm_rx_init(&ofdm_tx, cell.cp, cell.nof_prb)) { if (srslte_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb)) {
fprintf(stderr, "Error initializing FFT\n"); fprintf(stderr, "Error initializing FFT\n");
return; return;
} }
srslte_ofdm_set_normalize(&ofdm_tx, true); srslte_ofdm_set_normalize(&ofdm_rx, true);
srslte_ofdm_set_freq_shift(&ofdm_tx, 0.5); srslte_ofdm_set_freq_shift(&ofdm_rx, 0.5);
if (srslte_pusch_init(&pusch, cell)) { if (srslte_pusch_init(&pusch, cell)) {
mexErrMsgTxt("Error initiating PDSCH\n"); mexErrMsgTxt("Error initiating PDSCH\n");
@ -218,7 +218,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
if (!data_bytes) { if (!data_bytes) {
return; return;
} }
srslte_sch_set_max_noi(&pusch.dl_sch, max_iterations); srslte_sch_set_max_noi(&pusch.ul_sch, max_iterations);
input_fft = NULL; input_fft = NULL;
int r=-1; int r=-1;
@ -244,7 +244,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexPrintf("Input is after fft\n"); mexPrintf("Input is after fft\n");
} else { } else {
input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
srslte_ofdm_rx_sf(&ofdm_tx, input_signal, input_fft); srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft);
mexPrintf("Input is before fft\n"); mexPrintf("Input is before fft\n");
free(input_signal); free(input_signal);
} }
@ -294,7 +294,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_softbuffer_rx_free(&softbuffer); srslte_softbuffer_rx_free(&softbuffer);
srslte_chest_ul_free(&chest); srslte_chest_ul_free(&chest);
srslte_pusch_free(&pusch); srslte_pusch_free(&pusch);
srslte_ofdm_rx_free(&ofdm_tx); srslte_ofdm_rx_free(&ofdm_rx);
free(ce); free(ce);
free(data_bytes); free(data_bytes);

Loading…
Cancel
Save