Moved HARQ to MAC. Redesigned RA and DL/UL grant framework

master
ismagom 10 years ago
parent dc9464be9c
commit addd786e5f

@ -35,7 +35,7 @@
#include "cuhd_handler.hpp"
#include "srslte/cuhd/cuhd.h"
#define METADATA_VERBOSE
//#define METADATA_VERBOSE
//#define HIDE_MESSAGES

@ -1,7 +1,7 @@
enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1);
pdschConfig=struct('Modulation','QPSK','RV',0,'TxScheme','Port0');
addpath('../../debug/lte/phy/lib/phch/test')
addpath('../../debug/srslte/lib/phch/test')
TBs=1:111:15000;
e_bits=10000;

@ -10,7 +10,7 @@ Npackets = 1;
SNR_values = linspace(15,20,4);
%% Choose RMC
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.9',[1;0;0;1]);
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.4',[1;0;0;1]);
waveform = sum(waveform,2);
if ~isempty(recordedSignal)
@ -51,7 +51,7 @@ cec.InterpType = 'linear'; % 2D interpolation type
cec.InterpWindow = 'Centered'; % Interpolation window type
cec.InterpWinSize = 1; % Interpolation window size
addpath('../../debug/lte/phy/lib/phch/test')
addpath('../../debug/srslte/lib/phch/test')
decoded = zeros(size(SNR_values));
decoded_srslte = zeros(size(SNR_values));

@ -1,20 +1,14 @@
clear
ueConfig=struct('NCellID',1,'NULRB',6,'NSubframe',8,'RNTI',68,'CyclicPrefixUL','Normal','NTxAnts',1);
ueConfig=struct('NCellID',1,'NULRB',6,'NSubframe',1,'RNTI',18,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[1:4]','Modulation','QPSK','RV',0,'Shortened',0);
addpath('../../debug/lte/phy/lib/phch/test')
addpath('../../debug/srslte/lib/phch/test')
% TBs=0:13:211;
% cqilen=[0, 8, 17];
% mods={'QPSK','16QAM','64QAM'};
% rvs=0;
% betas=0:3:11;
TBs=88;
cqilen=0;
mods={'QPSK'};
rvs=0;
betas=0;
TBs=0:13:211;
cqilen=[0, 8, 17];
mods={'QPSK','16QAM','64QAM'};
rvs=0;
betas=[2.0 2.5 6.25];
for i=1:length(TBs)
for m=1:length(mods)
@ -28,9 +22,9 @@ for i=1:length(TBs)
puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r);
puschConfig.BetaCQI = 2+betas(bcqi);
puschConfig.BetaRI = 2+betas(bri);
puschConfig.BetaACK = 2+betas(back);
puschConfig.BetaCQI = betas(bcqi);
puschConfig.BetaRI = betas(bri);
puschConfig.BetaACK = betas(back);
if (betas(bri)>0)
ri_bit=randi(2,1,1)-1;

@ -2,13 +2,13 @@ clear
ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',0,'Modulation','16QAM','RV',0,'Shortened',0);
addpath('../../debug/lte/phy/lib/phch/test')
addpath('../../debug/srslte/lib/phch/test')
TBs=0:13:222;
cqilen=0;%[0, 8, 17];
cqilen=[0, 8, 17];
mods={'QPSK','16QAM','64QAM'};
rvs=0;%[0, 3];
betas=0:3:11;
rvs=[0, 3];
betas=[2.0 2.5 6.25];
for i=1:length(TBs)
@ -23,9 +23,9 @@ for i=1:length(TBs)
puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r);
puschConfig.BetaCQI = 2+betas(bcqi);
puschConfig.BetaRI = 2+betas(bri);
puschConfig.BetaACK = 2+betas(back);
puschConfig.BetaCQI = betas(bcqi);
puschConfig.BetaRI = betas(bri);
puschConfig.BetaACK = betas(back);
if (betas(bri)>0)
ri_bit=randi(2,1,1)-1;

@ -46,4 +46,4 @@ ADD_CUSTOM_TARGET (add_srslte_headers SOURCES ${HEADERS_ALL})
########################################################################
ADD_SUBDIRECTORY(lib)
ADD_SUBDIRECTORY(examples)
add_subdirectory(tutorial_examples)
#add_subdirectory(tutorial_examples)

@ -74,9 +74,10 @@ srslte_pbch_t pbch;
srslte_pcfich_t pcfich;
srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch;
srslte_harq_t harq_process;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_tx_t softbuffer;
srslte_regs_t regs;
srslte_ra_pdsch_t ra_dl;
srslte_ra_dl_dci_t ra_dl;
cf_t *sf_buffer = NULL, *output_buffer = NULL;
@ -253,15 +254,15 @@ void base_init() {
srslte_pdsch_set_rnti(&pdsch, 1234);
if (srslte_harq_init(&harq_process, cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
fprintf(stderr, "Error initiating soft buffer\n");
exit(-1);
}
}
void base_free() {
srslte_harq_free(&harq_process);
srslte_softbuffer_tx_free(&softbuffer);
srslte_pdsch_free(&pdsch);
srslte_pdcch_free(&pdcch);
srslte_regs_free(&regs);
@ -315,21 +316,25 @@ uint32_t prbset_to_bitmask() {
int update_radl() {
bzero(&ra_dl, sizeof(srslte_ra_pdsch_t));
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
ra_dl.harq_process = 0;
ra_dl.mcs_idx = mcs_idx;
ra_dl.ndi = 0;
ra_dl.rv_idx = 0;
ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask();
srslte_ra_dl_alloc(&ra_dl.prb_alloc, &ra_dl, cell.nof_prb);
srslte_ra_dl_alloc_re(&ra_dl.prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, SRSLTE_CP_NORM);
srslte_ra_mcs_from_idx_dl(mcs_idx, ra_dl.prb_alloc.slot[0].nof_prb, &ra_dl.mcs);
srslte_ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
srslte_ra_dl_grant_t dummy_grant;
srslte_ra_dl_dci_to_grant(&ra_dl, &dummy_grant, cell, 1, cfi, true);
srslte_ra_dl_grant_fprint(stdout, &dummy_grant);
printf("Type new MCS index and press Enter: "); fflush(stdout);
if (dummy_grant.mcs.tbs > dummy_grant.nof_bits) {
fprintf(stderr, "Invalid code rate %d/%d=%.2f\n", dummy_grant.mcs.tbs, dummy_grant.nof_bits, (float) dummy_grant.mcs.tbs / dummy_grant.nof_bits);
return -1;
}
return 0;
}
@ -403,7 +408,7 @@ void *net_thread_fnc(void *arg) {
do {
n = srslte_netsource_read(&net_source, &data_unpacked[rpm], DATA_BUFF_SZ-rpm);
if (n > 0) {
int nbytes = 1+(ra_dl.mcs.tbs-1)/8;
int nbytes = 1+(pdsch_cfg.grant.mcs.tbs-1)/8;
rpm += n;
INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes);
wpm = 0;
@ -537,13 +542,6 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error updating parameters from control port\n");
}
srslte_harq_reset(&harq_process);
if (srslte_harq_setup_dl(&harq_process, ra_dl.mcs, ra_dl.rv_idx, sf_idx, &ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return -1;
}
/* Transmit PDCCH + PDSCH only when there is data to send */
if (sf_idx != 0 && sf_idx != 5) {
if (net_port > 0) {
@ -552,8 +550,8 @@ int main(int argc, char **argv) {
INFO("Transmitting packet\n",0);
}
} else {
INFO("SF: %d, Generating %d random bits\n", sf_idx, ra_dl.mcs.tbs);
for (i=0;i<ra_dl.mcs.tbs;i++) {
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs.tbs);
for (i=0;i<pdsch_cfg.grant.mcs.tbs;i++) {
data[i] = rand()%2;
}
send_data = true;
@ -563,6 +561,12 @@ int main(int argc, char **argv) {
}
if (send_data) {
srslte_ra_dl_dci_to_grant(&ra_dl, &pdsch_cfg.grant, cell, sf_idx, cfi, true);
srslte_cbsegm(&pdsch_cfg.cb_segm, pdsch_cfg.grant.mcs.tbs);
srslte_softbuffer_tx_reset(&softbuffer);
pdsch_cfg.sf_idx = sf_idx;
pdsch_cfg.rv = 0;
srslte_dci_msg_pack_pdsch(&ra_dl, &dci_msg, SRSLTE_DCI_FORMAT1, cell.nof_prb, false);
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], 1234, sf_symbols, sf_idx, cfi)) {
@ -570,14 +574,14 @@ int main(int argc, char **argv) {
exit(-1);
}
if (srslte_pdsch_encode(&pdsch, &harq_process, data, sf_symbols)) {
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer, data, sf_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
exit(-1);
}
if (net_port > 0 && net_packet_ready) {
if (null_file_sink) {
srslte_bit_unpack_vector(data, data_tmp, ra_dl.mcs.tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1+(ra_dl.mcs.tbs-1)/8) < 0) {
srslte_bit_unpack_vector(data, data_tmp, pdsch_cfg.grant.mcs.tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1+(pdsch_cfg.grant.mcs.tbs-1)/8) < 0) {
fprintf(stderr, "Error sending data through UDP socket\n");
}
}
@ -598,7 +602,7 @@ int main(int argc, char **argv) {
} else {
#ifndef DISABLE_UHD
// FIXME
float norm_factor = (float) cell.nof_prb/15/sqrtf(ra_dl.prb_alloc.slot[0].nof_prb);
float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb);
srslte_vec_sc_prod_cfc(output_buffer, uhd_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
cuhd_send(uhd, output_buffer, sf_n_samples, true);
#endif

@ -566,7 +566,7 @@ void *plot_thread_run(void *arg) {
while(1) {
sem_wait(&plot_sem);
uint32_t nof_symbols = ue_dl.harq_process[0].dl_alloc.re_sf[plot_sf_idx];
uint32_t nof_symbols = ue_dl.pdsch_cfg.grant.nof_re;
for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i]));
if (isinf(tmp_plot[i])) {

@ -295,7 +295,8 @@ int main(int argc, char **argv) {
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
uint32_t sfn_offset;
rar_msg_t rar_msg;
srslte_ra_pusch_t ra_pusch;
srslte_ra_ul_dci_t ra_pusch;
srslte_ra_ul_grant_t ra_grant;
uint32_t rar_window_start = 0, rar_trials = 0, rar_window_stop = 0;
srslte_timestamp_t uhd_time;
srslte_timestamp_t next_tx_time;
@ -489,15 +490,16 @@ int main(int argc, char **argv) {
rar_unpack(data_rx, &rar_msg);
rar_msg_fprint(stdout, &rar_msg);
srslte_dci_rar_to_ra_ul(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, cell.nof_prb, &ra_pusch);
srslte_dci_rar_grant_t rar_grant;
rar_grant.hopping_flag = rar_msg.hopping_flag;
rar_grant.rba = rar_msg.rba;
rar_grant.trunc_mcs = rar_msg.mcs;
srslte_dci_rar_to_ul_grant(&rar_grant, cell, 0, 0, &ra_pusch, &ra_grant);
srslte_ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb);
srslte_ra_ul_alloc(&ra_pusch.prb_alloc, &ra_pusch, 0, cell.nof_prb);
srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_pusch.mcs.tbs);
srslte_bit_pack_vector((uint8_t*) conn_request_msg, data, ra_grant.mcs.tbs);
uint32_t n_ta = srslte_N_ta_new_rar(rar_msg.timing_adv_cmd);
printf("ta: %d, n_ta: %d\n", rar_msg.timing_adv_cmd, n_ta);
@ -515,7 +517,7 @@ int main(int argc, char **argv) {
printf("Setting CFO: %f (%f)\n", cfo, cfo*15000);
srslte_ue_ul_set_cfo(&ue_ul, cfo);
n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, &ra_pusch, data, ul_sf_idx, rar_msg.temp_c_rnti, ul_signal);
n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, &ra_grant, data, ul_sf_idx, 0, rar_msg.temp_c_rnti, ul_signal);
if (n < 0) {
fprintf(stderr, "Error encoding PUSCH\n");
exit(-1);

@ -126,8 +126,6 @@ typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t;
#define SRSLTE_NOF_LTE_BANDS 29
#define SRSLTE_NOF_TC_CB_SIZES 188
typedef enum SRSLTE_API {
SRSLTE_PHICH_NORM = 0,
SRSLTE_PHICH_EXT
@ -221,18 +219,12 @@ SRSLTE_API uint32_t srslte_N_ta_new_rar(uint32_t ta);
SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old,
uint32_t ta);
SRSLTE_API int srslte_cb_size(uint32_t index);
SRSLTE_API bool srslte_cb_size_isvalid(uint32_t size);
SRSLTE_API char *srslte_cp_string(srslte_cp_t cp);
SRSLTE_API char *srslte_mod_string(srslte_mod_t mod);
SRSLTE_API uint32_t srslte_mod_bits_x_symbol(srslte_mod_t mod);
SRSLTE_API int srslte_find_cb_index(uint32_t long_cb);
SRSLTE_API float srslte_band_fd(uint32_t earfcn);
SRSLTE_API int srslte_band_get_fd_band(uint32_t band,

@ -0,0 +1,58 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include <stdbool.h>
#include "srslte/config.h"
#ifndef CBSEGM_H
#define CBSEGM_H
#define SRSLTE_NOF_TC_CB_SIZES 188
typedef struct SRSLTE_API {
uint32_t F;
uint32_t C;
uint32_t K1;
uint32_t K2;
uint32_t C1;
uint32_t C2;
uint32_t tbs;
} srslte_cbsegm_t;
SRSLTE_API int srslte_cbsegm(srslte_cbsegm_t *s,
uint32_t tbs);
SRSLTE_API int srslte_cbsegm_cbsize(uint32_t index);
SRSLTE_API bool srslte_cbsegm_cbsize_isvalid(uint32_t size);
SRSLTE_API int srslte_cbsegm_cbindex(uint32_t long_cb);
#endif

@ -37,6 +37,7 @@
#define _TC_INTERL_H
#include "srslte/config.h"
#include <stdint.h>
typedef struct SRSLTE_API {
uint32_t *forward;

@ -46,8 +46,8 @@
#define SRSLTE_TCOD_RATE 3
#define SRSLTE_TCOD_TOTALTAIL 12
#define MAX_LONG_CB 6144
#define MAX_LONG_CODED (SRSLTE_TCOD_RATE*MAX_LONG_CB+SRSLTE_TCOD_TOTALTAIL)
#define SRSLTE_TCOD_MAX_LEN_CB 6144
#define SRSLTE_TCOD_MAX_LEN_CODED (SRSLTE_TCOD_RATE*SRSLTE_TCOD_MAX_LEN_CB+SRSLTE_TCOD_TOTALTAIL)
typedef float srslte_llr_t;

@ -28,7 +28,9 @@
/******************************************************************************
* File: dci.h
*
* Description: Downlink control information (DCI)
* Description: Downlink control information (DCI).
* Packing/Unpacking functions to convert between bit streams
* and packed DCI UL/DL grants defined in ra.h
*
* Reference: 3GPP TS 36.212 version 10.0.0 Release 10 Sec. 5.3.3
*****************************************************************************/
@ -79,25 +81,36 @@ typedef struct SRSLTE_API {
uint32_t nof_bits;
} srslte_dci_msg_t;
typedef struct SRSLTE_API {
uint32_t rba;
uint32_t trunc_mcs;
bool hopping_flag;
} srslte_dci_rar_grant_t;
/* Converts a received PDSCH DL scheduling DCI message
* to ra structures ready to be passed to the harq setup function
*/
SRSLTE_API int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg,
uint16_t msg_rnti,
srslte_cell_t cell,
uint32_t cfi,
srslte_ra_pdsch_t *ra_dl);
SRSLTE_API int srslte_dci_msg_to_ra_ul(srslte_dci_msg_t *msg,
uint32_t nof_prb,
uint32_t n_rb_ho,
srslte_ra_pusch_t *ra_ul);
SRSLTE_API int srslte_dci_rar_to_ra_ul(uint32_t rba,
uint32_t trunc_mcs,
bool hopping_flag,
uint32_t nof_prb,
srslte_ra_pusch_t *ra);
SRSLTE_API int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg,
uint16_t msg_rnti,
srslte_cell_t cell,
uint32_t cfi,
uint32_t sf_idx,
srslte_ra_dl_dci_t *dl_dci,
srslte_ra_dl_grant_t *grant);
SRSLTE_API int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg,
srslte_cell_t cell,
uint32_t N_srs,
uint32_t n_rb_ho,
srslte_ra_ul_dci_t *ul_dci,
srslte_ra_ul_grant_t *grant);
SRSLTE_API int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar,
srslte_cell_t cell,
uint32_t N_srs,
uint32_t n_rb_ho,
srslte_ra_ul_dci_t *ul_dci,
srslte_ra_ul_grant_t *grant);
SRSLTE_API srslte_dci_format_t srslte_dci_format_from_string(char *str);
@ -118,23 +131,23 @@ SRSLTE_API void srslte_dci_msg_type_fprint(FILE *f,
srslte_dci_msg_type_t type);
// For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PUSCH_SCHED
SRSLTE_API int srslte_dci_msg_pack_pusch(srslte_ra_pusch_t *data,
SRSLTE_API int srslte_dci_msg_pack_pusch(srslte_ra_ul_dci_t *data,
srslte_dci_msg_t *msg,
uint32_t nof_prb);
SRSLTE_API int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg,
srslte_ra_pusch_t *data,
srslte_ra_ul_dci_t *data,
uint32_t nof_prb);
// For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED
SRSLTE_API int srslte_dci_msg_pack_pdsch(srslte_ra_pdsch_t *data,
SRSLTE_API int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data,
srslte_dci_msg_t *msg,
srslte_dci_format_t format,
uint32_t nof_prb,
bool crc_is_crnti);
SRSLTE_API int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg,
srslte_ra_pdsch_t *data,
srslte_ra_dl_dci_t *data,
uint32_t nof_prb,
bool crc_is_crnti);

@ -1,98 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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: harq.h
*
* Description: Hybrid Automatic Repeat Request (HARQ)
*
* Reference:
*****************************************************************************/
#ifndef HARQ_
#define HARQ_
#include "srslte/config.h"
#include "srslte/common/phy_common.h"
#include "srslte/phch/ra.h"
typedef struct SRSLTE_API {
uint32_t F;
uint32_t C;
uint32_t K1;
uint32_t K2;
uint32_t C1;
uint32_t C2;
} srslte_harq_cbsegm_t;
typedef struct SRSLTE_API {
srslte_ra_mcs_t mcs;
uint32_t rv;
uint32_t sf_idx;
srslte_ra_dl_alloc_t dl_alloc;
srslte_ra_ul_alloc_t ul_alloc;
srslte_cell_t cell;
uint32_t nof_re; // Number of RE per subframe
uint32_t nof_bits; // Number of bits per subframe
uint32_t nof_symb; // Number of symbols per subframe
uint32_t nof_prb; // Number of allocated PRB per subframe.
uint32_t max_cb;
uint32_t w_buff_size;
float **pdsch_w_buff_f;
uint8_t **pdsch_w_buff_c;
srslte_harq_cbsegm_t cb_segm;
} srslte_harq_t;
SRSLTE_API int srslte_harq_init(srslte_harq_t * q,
srslte_cell_t cell);
SRSLTE_API int srslte_harq_setup_dl(srslte_harq_t *p,
srslte_ra_mcs_t mcs,
uint32_t rv,
uint32_t sf_idx,
srslte_ra_dl_alloc_t *prb_alloc);
SRSLTE_API int srslte_harq_setup_ul(srslte_harq_t *p,
srslte_ra_mcs_t mcs,
uint32_t rv,
uint32_t sf_idx,
srslte_ra_ul_alloc_t *prb_alloc);
SRSLTE_API void srslte_harq_reset(srslte_harq_t *p);
SRSLTE_API void srslte_harq_free(srslte_harq_t *p);
SRSLTE_API int srslte_harq_codeblock_segmentation(srslte_harq_cbsegm_t *s,
uint32_t tbs);
#endif

@ -46,12 +46,11 @@
#include "srslte/phch/dci.h"
#include "srslte/phch/regs.h"
#include "srslte/phch/sch.h"
#include "srslte/phch/harq.h"
#include "srslte/phch/pdsch_cfg.h"
#define SRSLTE_PDSCH_MAX_TDEC_ITERS 5
/* PDSCH object */
typedef struct SRSLTE_API {
srslte_cell_t cell;
@ -87,25 +86,29 @@ SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
uint16_t rnti);
SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t *q,
srslte_harq_t *harq_process,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_encode_rnti(srslte_pdsch_t *q,
srslte_harq_t *harq_process,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint16_t rnti,
cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t *q,
srslte_harq_t *harq_process,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols,
cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate,
uint8_t *data);
SRSLTE_API int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
srslte_harq_t *harq_process,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols,
cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate,

@ -0,0 +1,51 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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: pdsch_cfg.h
*
* Description: Physical downlink shared channel configuration
*
* Reference: 3GPP TS 36.211 version 10.0.0 Release 10 Sec. 6.4
*****************************************************************************/
#ifndef PDSCHCFG_
#define PDSCHCFG_
#include "srslte/phch/ra.h"
#include "srslte/phch/softbuffer.h"
#include "srslte/fec/cbsegm.h"
typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm;
srslte_ra_dl_grant_t grant;
uint32_t rv;
uint32_t sf_idx;
} srslte_pdsch_cfg_t;
#endif

@ -45,7 +45,7 @@
#include "srslte/scrambling/scrambling.h"
#include "srslte/phch/regs.h"
#include "srslte/phch/sch.h"
#include "srslte/phch/harq.h"
#include "srslte/phch/pusch_cfg.h"
#include "srslte/dft/dft_precoding.h"
#define SRSLTE_PUSCH_MAX_TDEC_ITERS 5
@ -110,31 +110,36 @@ SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q,
uint16_t rnti);
SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q,
srslte_harq_t *harq_process,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
cf_t *sf_symbols);
SRSLTE_API int srslte_pusch_encode_rnti(srslte_pusch_t *q,
srslte_harq_t *harq_process,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint16_t rnti,
cf_t *sf_symbols);
SRSLTE_API int srslte_pusch_uci_encode(srslte_pusch_t *q,
srslte_harq_t *harq_process,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
srslte_uci_data_t uci_data,
cf_t *sf_symbols);
SRSLTE_API int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q,
srslte_harq_t *harq,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
srslte_uci_data_t uci_data,
uint16_t rnti,
cf_t *sf_symbols);
SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q,
srslte_harq_t *harq_process,
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols,
cf_t *ce,
float noise_estimate,

@ -0,0 +1,52 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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: pdsch_cfg.h
*
* Description: Physical downlink shared channel configuration
*
* Reference: 3GPP TS 36.211 version 10.0.0 Release 10 Sec. 6.4
*****************************************************************************/
#ifndef PUSCHCFG_
#define PUSCHCFG_
#include "srslte/phch/ra.h"
#include "srslte/phch/softbuffer.h"
#include "srslte/fec/cbsegm.h"
typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm;
srslte_ra_ul_grant_t grant;
uint32_t rv;
uint32_t sf_idx;
srslte_cp_t cp;
} srslte_pusch_cfg_t;
#endif

@ -29,6 +29,7 @@
* File: ra.h
*
* Description: Structures and utility functions for DL/UL resource allocation.
* Convert an UL/DL unpacket DCI message to a resource allocation
*
* Reference: 3GPP TS 36.213 version 10.0.1 Release 10
*****************************************************************************/
@ -42,6 +43,10 @@
#include "srslte/config.h"
#include "srslte/common/phy_common.h"
/**************************************************
* Common structures used for Resource Allocation
**************************************************/
typedef struct SRSLTE_API {
srslte_mod_t mod;
int tbs;
@ -78,39 +83,72 @@ typedef struct SRSLTE_API {
} mode;
} srslte_ra_type2_t;
typedef struct SRSLTE_API {
bool prb_idx[SRSLTE_MAX_PRB];
uint32_t nof_prb;
} srslte_ra_prb_slot_t;
typedef struct SRSLTE_API {
srslte_ra_prb_slot_t slot[2];
uint32_t lstart;
uint32_t re_sf[SRSLTE_NSUBFRAMES_X_FRAME];
} srslte_ra_dl_alloc_t;
/**************************************************
* Structures used for Downlink Resource Allocation
**************************************************/
typedef struct SRSLTE_API {
uint32_t n_prb[2];
uint32_t n_prb_tilde[2];
uint32_t L_prb;
uint32_t freq_hopping;
} srslte_ra_ul_alloc_t;
bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t lstart;
uint32_t nof_re;
uint32_t nof_bits;
uint32_t nof_symb;
uint32_t nof_prb;
uint32_t Qm;
srslte_ra_mcs_t mcs;
} srslte_ra_dl_grant_t;
/** Unpacked DCI message for DL grant */
typedef struct SRSLTE_API {
enum {
SRSLTE_RA_DCI_FORMAT1,
SRSLTE_RA_DCI_FORMAT1A,
SRSLTE_RA_DCI_FORMAT1C,
} dci_format;
srslte_ra_type_t alloc_type;
union {
srslte_ra_type0_t type0_alloc;
srslte_ra_type1_t type1_alloc;
srslte_ra_type2_t type2_alloc;
};
srslte_ra_dl_alloc_t prb_alloc;
uint32_t mcs_idx;
srslte_ra_mcs_t mcs;
uint32_t harq_process;
uint32_t rv_idx;
bool ndi;
} srslte_ra_pdsch_t;
} srslte_ra_dl_dci_t;
/**************************************************
* Structures used for Uplink Resource Allocation
**************************************************/
typedef struct SRSLTE_API {
uint32_t n_prb[2];
uint32_t n_prb_tilde[2];
uint32_t L_prb;
uint32_t freq_hopping;
uint32_t lstart;
uint32_t nof_re;
uint32_t nof_bits;
uint32_t nof_symb;
uint32_t M_sc;
uint32_t M_sc_init;
uint32_t Qm;
srslte_ra_mcs_t mcs;
} srslte_ra_ul_grant_t;
/** Unpacked DCI Format0 message */
typedef struct SRSLTE_API {
/* 36.213 Table 8.4-2: SRSLTE_RA_PUSCH_HOP_HALF is 0 for < 10 Mhz and 10 for > 10 Mhz.
* SRSLTE_RA_PUSCH_HOP_QUART is 00 for > 10 Mhz and SRSLTE_RA_PUSCH_HOP_QUART_NEG is 01 for > 10 Mhz.
@ -123,57 +161,49 @@ typedef struct SRSLTE_API {
SRSLTE_RA_PUSCH_HOP_TYPE2 = 3
} freq_hop_fl;
srslte_ra_ul_alloc_t prb_alloc;
srslte_ra_ul_grant_t prb_alloc;
srslte_ra_type2_t type2_alloc;
uint32_t mcs_idx;
srslte_ra_mcs_t mcs;
uint32_t rv_idx; // If set to non-zero, a retransmission is requested with the same modulation
// than before (SRSLTE_DCI_FORMAT0 message, see also 8.6.1 in 36.2313).
uint32_t rv_idx;
uint32_t n_dmrs;
bool ndi;
bool cqi_request;
} srslte_ra_pusch_t;
} srslte_ra_ul_dci_t;
SRSLTE_API void srslte_ra_prb_fprint(FILE *f,
srslte_ra_prb_slot_t *prb,
uint32_t nof_prb);
SRSLTE_API int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb,
srslte_ra_pdsch_t *ra,
uint32_t nof_prb);
SRSLTE_API int srslte_ra_ul_alloc(srslte_ra_ul_alloc_t *prb,
srslte_ra_pusch_t *ra,
uint32_t n_rb_ho,
uint32_t nof_prb);
/**************************************************
* Functions
**************************************************/
SRSLTE_API void srslte_ra_dl_alloc_re(srslte_ra_dl_alloc_t *prb_dist,
uint32_t nof_prb,
uint32_t nof_ports,
uint32_t nof_ctrl_symbols,
srslte_cp_t cp);
SRSLTE_API uint32_t srslte_ra_nprb_dl(srslte_ra_pdsch_t *ra,
uint32_t nof_prb);
SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t* dci,
srslte_ra_dl_grant_t* grant,
srslte_cell_t cell,
uint32_t sf_idx,
uint32_t cfi,
bool crc_is_crnti);
SRSLTE_API uint32_t srslte_ra_nprb_ul(srslte_ra_pusch_t *ra,
uint32_t nof_prb);
SRSLTE_API void srslte_dl_dci_to_grant_nof_re(srslte_ra_dl_grant_t *grant,
srslte_cell_t cell,
uint32_t sf_idx,
uint32_t nof_ctrl_symbols);
SRSLTE_API int srslte_ra_mcs_from_idx_dl(uint32_t mcs_idx,
uint32_t nof_prb,
srslte_ra_mcs_t *mcs);
SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci,
srslte_ra_ul_grant_t *grant,
srslte_cell_t cell,
uint32_t n_rb_ho,
uint32_t N_srs);
SRSLTE_API int srslte_ra_mcs_from_idx_ul(uint32_t mcs_idx,
uint32_t nof_prb,
srslte_ra_mcs_t *mcs);
SRSLTE_API int srslte_ra_tbs_from_idx_format1c(uint32_t tbs_idx);
SRSLTE_API int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci,
srslte_ra_ul_grant_t *grant,
uint32_t n_rb_ho,
uint32_t nof_prb);
SRSLTE_API int srslte_ra_tbs_from_idx(uint32_t tbs_idx,
uint32_t n_prb);
uint32_t n_prb);
SRSLTE_API int srslte_ra_tbs_to_table_idx(uint32_t tbs,
uint32_t n_prb);
@ -201,11 +231,20 @@ SRSLTE_API uint32_t srslte_ra_type2_ngap(uint32_t nof_prb,
SRSLTE_API uint32_t srslte_ra_type1_N_rb(uint32_t nof_prb);
SRSLTE_API void srslte_ra_pdsch_fprint(FILE *f,
srslte_ra_pdsch_t *ra,
srslte_ra_dl_dci_t *ra,
uint32_t nof_prb);
SRSLTE_API void srslte_ra_dl_grant_fprint(FILE *f,
srslte_ra_dl_grant_t *grant);
SRSLTE_API void srslte_ra_prb_fprint(FILE *f,
srslte_ra_dl_grant_t *grant);
SRSLTE_API void srslte_ra_pusch_fprint(FILE *f,
srslte_ra_pusch_t *ra,
srslte_ra_ul_dci_t *ra,
uint32_t nof_prb);
SRSLTE_API void srslte_ra_ul_grant_fprint(FILE *f,
srslte_ra_ul_grant_t *grant);
#endif /* RB_ALLOC_H_ */

@ -42,7 +42,8 @@
#include "srslte/fec/turbocoder.h"
#include "srslte/fec/turbodecoder.h"
#include "srslte/fec/crc.h"
#include "srslte/phch/harq.h"
#include "srslte/phch/pdsch_cfg.h"
#include "srslte/phch/pusch_cfg.h"
#include "srslte/phch/uci.h"
#define SRSLTE_PDSCH_MAX_TDEC_ITERS 5
@ -58,7 +59,7 @@
/* DL-SCH AND UL-SCH common functions */
typedef struct SRSLTE_API {
uint32_t nof_iterations;
float average_nof_iterations;
@ -86,31 +87,42 @@ SRSLTE_API float srslte_sch_average_noi(srslte_sch_t *q);
SRSLTE_API uint32_t srslte_sch_last_noi(srslte_sch_t *q);
SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q,
srslte_harq_t *harq_process,
uint8_t *data,
uint8_t *e_bits);
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint8_t *e_bits);
SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q,
srslte_harq_t *harq_process,
float *e_bits,
uint8_t *data);
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
float *e_bits,
uint8_t *data);
SRSLTE_API int srslte_ulsch_encode(srslte_sch_t *q,
srslte_harq_t *harq_process,
uint8_t *data,
uint8_t *g_bits,
uint8_t *q_bits);
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint8_t *g_bits,
uint8_t *q_bits);
SRSLTE_API int srslte_ulsch_uci_encode(srslte_sch_t *q,
srslte_harq_t *harq_process,
uint8_t *data,
srslte_uci_data_t uci_data,
uint8_t *g_bits,
uint8_t *q_bits);
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
srslte_uci_data_t uci_data,
uint8_t *g_bits,
uint8_t *q_bits);
SRSLTE_API int srslte_ulsch_decode(srslte_sch_t *q,
srslte_harq_t *harq_process,
float *e_bits,
uint8_t *data);
srslte_pusch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
float *e_bits,
uint8_t *data);
SRSLTE_API uint32_t srslte_sch_find_Ioffset_ack(float beta);
SRSLTE_API uint32_t srslte_sch_find_Ioffset_cqi(float beta);
SRSLTE_API uint32_t srslte_sch_find_Ioffset_ri(float beta);
#endif

@ -0,0 +1,71 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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: softbuffer.h
*
* Description: Buffer for RX and TX soft bits. This should be provided by MAC.
* Provided here basically for the examples.
*
* Reference:
*****************************************************************************/
#ifndef SOFTBUFFER_
#define SOFTBUFFER_
#include "srslte/config.h"
#include "srslte/common/phy_common.h"
typedef struct SRSLTE_API {
uint32_t max_cb;
uint32_t buff_size;
float **buffer_f;
} srslte_softbuffer_rx_t;
typedef struct SRSLTE_API {
uint32_t max_cb;
uint32_t buff_size;
uint8_t **buffer_b;
} srslte_softbuffer_tx_t;
SRSLTE_API int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t * q,
srslte_cell_t cell);
SRSLTE_API void srslte_softbuffer_rx_reset(srslte_softbuffer_rx_t *p);
SRSLTE_API void srslte_softbuffer_rx_free(srslte_softbuffer_rx_t *p);
SRSLTE_API int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t * q,
srslte_cell_t cell);
SRSLTE_API void srslte_softbuffer_tx_reset(srslte_softbuffer_tx_t *p);
SRSLTE_API void srslte_softbuffer_tx_free(srslte_softbuffer_tx_t *p);
#endif

@ -38,14 +38,13 @@
#include "srslte/config.h"
#include "srslte/common/phy_common.h"
#include "srslte/phch/harq.h"
#include "srslte/phch/pusch_cfg.h"
#include "srslte/fec/crc.h"
#define SRSLTE_UCI_MAX_CQI_LEN_PUSCH 512
#define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13
#define SRSLTE_UCI_CQI_CODED_PUCCH_B 20
typedef struct SRSLTE_API {
srslte_crc_t crc;
uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH];
@ -72,28 +71,28 @@ SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q);
SRSLTE_API void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t *q);
SRSLTE_API int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q,
srslte_pusch_cfg_t *cfg,
uint8_t *cqi_data,
uint32_t cqi_len,
float beta,
uint32_t Q_prime_ri,
srslte_harq_t *harq_process,
uint8_t *q_bits);
SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data,
uint32_t cqi_len,
uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]);
SRSLTE_API int srslte_uci_encode_ack(uint8_t data,
uint32_t O_cqi,
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint32_t O_cqi,
float beta,
srslte_harq_t *harq_process,
uint32_t H_prime_total,
uint8_t *q_bits);
SRSLTE_API int srslte_uci_encode_ri(uint8_t data,
uint32_t O_cqi,
SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint32_t O_cqi,
float beta,
srslte_harq_t *harq_process,
uint32_t H_prime_total,
uint8_t *q_bits);

@ -64,6 +64,7 @@
#include "srslte/fec/tc_interl.h"
#include "srslte/fec/turbocoder.h"
#include "srslte/fec/turbodecoder.h"
#include "srslte/fec/cbsegm.h"
#include "srslte/fec/rm_conv.h"
#include "srslte/fec/rm_turbo.h"
@ -87,7 +88,7 @@
#include "srslte/phch/cqi.h"
#include "srslte/phch/dci.h"
#include "srslte/phch/harq.h"
#include "srslte/phch/softbuffer.h"
#include "srslte/phch/pbch.h"
#include "srslte/phch/pcfich.h"
#include "srslte/phch/pdcch.h"

@ -49,6 +49,7 @@
#include "srslte/phch/pcfich.h"
#include "srslte/phch/pdcch.h"
#include "srslte/phch/pdsch.h"
#include "srslte/phch/pdsch_cfg.h"
#include "srslte/phch/phich.h"
#include "srslte/phch/ra.h"
#include "srslte/phch/regs.h"
@ -58,19 +59,17 @@
#include "srslte/config.h"
#define SRSLTE_UE_UL_NOF_HARQ_PROCESSES 8
typedef struct SRSLTE_API {
srslte_pcfich_t pcfich;
srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch;
srslte_phich_t phich;
srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES];
srslte_regs_t regs;
srslte_ofdm_t fft;
srslte_chest_dl_t chest;
srslte_ra_pdsch_t ra_dl;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_rx_t softbuffer;
srslte_cell_t cell;

@ -82,8 +82,8 @@ public:
uint32_t get_harq_process();
private:
union {
srslte_ra_pusch_t ul_grant;
srslte_ra_pdsch_t dl_grant;
srslte_ra_ul_dci_t ul_grant;
srslte_ra_dl_dci_t dl_grant;
};
direction_t dir;
};

@ -63,8 +63,10 @@ typedef struct SRSLTE_API {
float current_cfo;
srslte_pusch_cfg_t pusch_cfg;
srslte_refsignal_ul_t dmrs;
srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES];
srslte_softbuffer_tx_t softbuffer;
srslte_pusch_t pusch;
srslte_pucch_t pucch;
@ -103,33 +105,44 @@ SRSLTE_API int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q,
srslte_ra_pusch_t *ra_ul,
srslte_ra_ul_grant_t *grant,
uint8_t *data,
uint32_t sf_idx,
uint32_t rv,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q,
srslte_ra_pusch_t *ra_ul,
srslte_ra_ul_grant_t *grant,
uint8_t *data,
uint32_t sf_idx,
uint32_t rv,
uint16_t rnti,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q,
srslte_ra_pusch_t *ra_ul,
srslte_ra_ul_grant_t *grant,
uint8_t *data,
srslte_uci_data_t uci_data,
uint32_t sf_idx,
uint32_t rv,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q,
srslte_ra_pusch_t *ra_ul,
srslte_ra_ul_grant_t *grant,
uint8_t *data,
srslte_uci_data_t uci_data,
uint32_t sf_idx,
uint32_t rv,
uint16_t rnti,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q,
srslte_pusch_cfg_t *cfg,
uint8_t *data,
srslte_uci_data_t uci_data,
uint16_t rnti,
cf_t *output_signal);
SRSLTE_API void srslte_ue_ul_reset(srslte_ue_ul_t *q);
SRSLTE_API void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q,

@ -27,7 +27,8 @@
#include "srslte/srslte.h"
#include "srslte/ue_itf/queue.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srslte/ue_itf/ul_sched_grant.h"
#include "srslte/ue_itf/dl_sched_grant.h"
#include "srslte/ue_itf/phy_params.h"
#ifndef UEDLBUFFER_H
@ -64,10 +65,11 @@ namespace ue {
bool init_cell(srslte_cell_t cell, phy_params *params_db);
void free_cell();
bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time);
bool get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant);
bool get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant);
bool decode_ack(srslte::ue::sched_grant pusch_grant);
bool decode_data(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO
bool get_ul_grant(pdcch_ul_search_t mode, ul_sched_grant *grant);
bool get_dl_grant(pdcch_dl_search_t mode, dl_sched_grant *grant);
bool decode_ack(ul_sched_grant *pusch_grant);
bool decode_data(dl_sched_grant *pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/NOK
private:
phy_params *params_db;
srslte_cell_t cell;

@ -0,0 +1,94 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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/ue_itf/sched_grant.h"
#ifndef UEDLSCHEDGRANT_H
#define UEDLSCHEDGRANT_H
namespace srslte {
namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class SRSLTE_API dl_sched_grant : public sched_grant {
public:
dl_sched_grant(uint16_t rnti) : sched_grant(rnti) {}
uint32_t get_rv() {
return dl_dci.rv_idx;
}
void set_rv(uint32_t rv) {
dl_dci.rv_idx = rv;
}
bool get_ndi() {
return dl_dci.ndi;
}
void set_ndi(bool value) {
dl_dci.ndi = value;
}
uint32_t get_harq_process() {
return dl_dci.harq_process;
}
void get_dl_grant(srslte_ra_dl_grant_t *ul_grant) {
memcpy(ul_grant, &grant, sizeof(srslte_ra_dl_grant_t));
}
bool is_sps_release() {
return false;
}
uint32_t get_tbs() {
return grant.mcs.tbs;
}
uint32_t get_ncce() {
return ncce;
}
bool create_from_dci(srslte_dci_msg_t *msg, srslte_cell_t cell, uint32_t cfi, uint32_t sf_idx, uint32_t ncce_) {
ncce = ncce_;
if (srslte_dci_msg_to_dl_grant(msg, rnti, cell, cfi, sf_idx, &dl_dci, &grant)) {
return false;
} else {
return true;
}
}
void get_pdsch_cfg(uint32_t sf_idx, srslte_pdsch_cfg_t *cfg) {
srslte_cbsegm(&cfg->cb_segm, grant.mcs.tbs);
memcpy(&cfg->grant, &grant, sizeof(srslte_ra_dl_grant_t));
cfg->sf_idx = sf_idx;
cfg->rv = dl_dci.rv_idx;
}
private:
srslte_ra_dl_grant_t grant;
srslte_ra_dl_dci_t dl_dci;
uint32_t ncce;
};
}
}
#endif

@ -59,7 +59,11 @@ typedef _Complex float cf_t;
class SRSLTE_API phy
{
public:
phy() {
started = false;
is_sfn_synched = false;
cell_is_set = false;
}
bool init(radio *radio_handler, tti_sync *ttisync);
void stop();
@ -87,7 +91,7 @@ public:
void set_timeadv(uint32_t ta_cmd);
// Generate Msg3 UL grant from RAR
void rar_ul_grant(uint32_t rba, uint32_t trunc_mcs, bool hopping_flag, sched_grant *grant);
void rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant);
// Get status
bool status_is_idle();
@ -114,8 +118,8 @@ private:
srslte_cell_t cell;
bool cell_is_set;
bool is_sfn_synched = false;
bool started = false;
bool is_sfn_synched;
bool started;
srslte_ue_sync_t ue_sync;
srslte_ue_mib_t ue_mib;

@ -38,6 +38,11 @@ namespace ue {
class SRSLTE_API prach {
public:
prach() {
params_db = NULL;
initiated = false;
signal_buffer = NULL;
}
bool init_cell(srslte_cell_t cell, phy_params *params_db);
void free_cell();
bool prepare_to_send(uint32_t preamble_idx);
@ -51,7 +56,7 @@ namespace ue {
bool initiated = false;
uint32_t len;
cf_t *buffer[64];
srslte_prach_t prach;
srslte_prach_t prach_obj;
uint32_t transmitted_tti;
srslte_cell_t cell;
cf_t *signal_buffer;

@ -37,34 +37,20 @@ namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class SRSLTE_API sched_grant {
public:
typedef enum {DOWNLINK=0, UPLINK=1} direction_t;
sched_grant(direction_t direction, uint16_t rnti);
uint16_t get_rnti();
uint32_t get_rv();
void set_rv(uint32_t rv);
bool get_ndi();
void set_ndi(bool value);
bool get_cqi_request();
int get_harq_process();
bool is_uplink();
bool is_downlink();
void* get_grant_ptr();
bool is_sps_release();
void set_ncce(uint32_t ncce);
uint32_t get_ncce();
uint32_t get_tbs();
uint32_t get_current_tx_nb();
void set_current_tx_nb(uint32_t current_tx_nb);
sched_grant(uint16_t rnti_) {
rnti = rnti_;
}
uint16_t get_rnti() {
return rnti;
}
virtual uint32_t get_rv() = 0;
virtual void set_rv(uint32_t rv) = 0;
virtual bool get_ndi() = 0;
virtual void set_ndi(bool value) = 0;
virtual bool is_sps_release() = 0;
virtual uint32_t get_tbs() = 0;
protected:
union {
srslte_ra_pusch_t ul_grant;
srslte_ra_pdsch_t dl_grant;
};
uint32_t current_tx_nb;
direction_t dir;
uint16_t rnti;
uint32_t ncce;
};
}

@ -28,7 +28,8 @@
#include "srslte/srslte.h"
#include "srslte/common/radio.h"
#include "srslte/ue_itf/queue.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srslte/ue_itf/ul_sched_grant.h"
#include "srslte/ue_itf/dl_sched_grant.h"
#include "srslte/ue_itf/phy_params.h"
#ifndef UEULBUFFER_H
@ -48,26 +49,27 @@ namespace ue {
void free_cell();
void set_tti(uint32_t tti);
void set_current_tx_nb(uint32_t current_tx_nb);
bool generate_ack(bool ack, sched_grant last_dl_grant);
bool generate_ack(bool ack, dl_sched_grant *last_dl_grant);
bool generate_ack(bool ack[2]);
bool generate_sr();
bool generate_cqi_report();
bool uci_ready();
bool generate_data();
bool generate_data(sched_grant pusch_grant, uint8_t *payload);
bool generate_data(ul_sched_grant *pusch_grant, uint8_t *payload);
bool send(radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time);
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
private:
phy_params *params_db;
srslte_cell_t cell;
srslte_ue_ul_t ue_ul;
bool cell_initiated;
cf_t* signal_buffer;
uint32_t current_tx_nb;
uint32_t last_n_cce;
srslte_uci_data_t uci_data;
bool uci_pending;
phy_params *params_db;
srslte_cell_t cell;
srslte_ue_ul_t ue_ul;
srslte_pusch_cfg_t pusch_cfg;
bool cell_initiated;
cf_t* signal_buffer;
uint32_t current_tx_nb;
uint32_t last_n_cce;
srslte_uci_data_t uci_data;
bool uci_pending;
};
}

@ -0,0 +1,117 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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/ue_itf/sched_grant.h"
#ifndef UEULSCHEDGRANT_H
#define UEULSCHEDGRANT_H
namespace srslte {
namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class SRSLTE_API ul_sched_grant : public sched_grant {
public:
ul_sched_grant(uint16_t rnti) : sched_grant(rnti) {}
uint32_t get_rv() {
return ul_dci.rv_idx;
}
void set_rv(uint32_t rv) {
ul_dci.rv_idx = rv;
}
bool get_ndi() {
return ul_dci.ndi;
}
void set_ndi(bool value) {
ul_dci.ndi = value;
}
bool get_cqi_request() {
return ul_dci.cqi_request;
}
void get_ul_grant(srslte_ra_ul_grant_t *ul_grant) {
memcpy(ul_grant, &grant, sizeof(srslte_ra_ul_grant_t));
}
bool is_sps_release() {
return false;
}
uint32_t get_tbs() {
return grant.mcs.tbs;
}
uint32_t get_current_tx_nb() {
return current_tx_nb;
}
void set_current_tx_nb(uint32_t current_tx_nb) {
current_tx_nb = current_tx_nb;
}
uint32_t get_I_lowest() {
return grant.n_prb[0];
}
uint32_t get_n_dmrs() {
return ul_dci.n_dmrs;
}
bool create_from_dci(srslte_dci_msg_t *msg, srslte_cell_t cell, uint32_t N_srs, uint32_t n_rb_ho) {
if (srslte_dci_msg_to_ul_grant(msg, cell, N_srs, n_rb_ho, &ul_dci, &grant)) {
return false;
} else {
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, &ul_dci, cell.nof_prb);
}
return true;
}
}
bool create_from_rar(srslte_dci_rar_grant_t *rar, srslte_cell_t cell, uint32_t N_srs, uint32_t n_rb_ho) {
if (srslte_dci_rar_to_ul_grant(rar, cell, N_srs, n_rb_ho, &ul_dci, &grant)) {
return false;
} else {
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, &ul_dci, cell.nof_prb);
}
return true;
}
}
void to_pusch_cfg(uint32_t sf_idx, srslte_cp_t cp, srslte_pusch_cfg_t *cfg) {
srslte_cbsegm(&cfg->cb_segm, grant.mcs.tbs);
cfg->cp = cp;
memcpy(&cfg->grant, &grant, sizeof(srslte_ra_ul_grant_t));
cfg->rv = ul_dci.rv_idx;
cfg->sf_idx = sf_idx;
}
private:
srslte_ra_ul_grant_t grant;
srslte_ra_ul_dci_t ul_dci;
uint32_t current_tx_nb;
uint16_t rnti;
};
}
}
#endif

@ -85,7 +85,7 @@ int main(int argc, char **argv) {
srslte_chest_dl_t est;
srslte_precoding_t cheq;
cf_t *input = NULL, *ce = NULL, *h = NULL, *output = NULL;
int i, j, n_port, sf_idx, cid, num_re;
int i, j, n_port=0, sf_idx=0, cid=0, num_re;
int ret = -1;
int max_cid;
FILE *fmatlab = NULL;

@ -35,21 +35,6 @@
#include "srslte/common/phy_common.h"
#include "srslte/common/sequence.h"
const uint32_t tc_cb_sizes[SRSLTE_NOF_TC_CB_SIZES] = { 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120,
128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232,
240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344,
352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456,
464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624,
640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848,
864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1056, 1088,
1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472,
1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856,
1888, 1920, 1952, 1984, 2016, 2048, 2112, 2176, 2240, 2304, 2368, 2432,
2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136, 3200,
3264, 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, 3904, 3968,
4032, 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736,
4800, 4864, 4928, 4992, 5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504,
5568, 5632, 5696, 5760, 5824, 5888, 5952, 6016, 6080, 6144 };
/* Returns true if the structure pointed by cell has valid parameters
*/
@ -135,27 +120,6 @@ bool srslte_N_id_1_isvalid(uint32_t N_id_1) {
}
}
/*
* Returns Turbo coder interleaver size for Table 5.1.3-3 (36.212) index
*/
int srslte_cb_size(uint32_t index) {
if (index < SRSLTE_NOF_TC_CB_SIZES) {
return (int) tc_cb_sizes[index];
} else {
return SRSLTE_ERROR;
}
}
bool srslte_cb_size_isvalid(uint32_t size) {
for (int i=0;i<SRSLTE_NOF_TC_CB_SIZES;i++) {
if (tc_cb_sizes[i] == size) {
return true;
}
}
return false;
}
char *srslte_mod_string(srslte_mod_t mod) {
switch (mod) {
case SRSLTE_MOD_BPSK:
@ -219,21 +183,6 @@ uint32_t srslte_N_ta_new_rar(uint32_t ta) {
return ta*16;
}
/*
* Finds index of minimum K>=long_cb in Table 5.1.3-3 of 36.212
*/
int srslte_find_cb_index(uint32_t long_cb) {
int j = 0;
while (j < SRSLTE_NOF_TC_CB_SIZES && tc_cb_sizes[j] < long_cb) {
j++;
}
if (j == SRSLTE_NOF_TC_CB_SIZES) {
return SRSLTE_ERROR;
} else {
return j;
}
}
int srslte_sampling_freq_hz(uint32_t nof_prb) {
int n = srslte_symbol_sz(nof_prb);

@ -0,0 +1,137 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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 <strings.h>
#include <math.h>
#include "srslte/fec/turbodecoder.h"
#include "srslte/fec/cbsegm.h"
#include "srslte/utils/debug.h"
const uint32_t tc_cb_sizes[SRSLTE_NOF_TC_CB_SIZES] = { 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120,
128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232,
240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344,
352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456,
464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624,
640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848,
864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1056, 1088,
1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472,
1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856,
1888, 1920, 1952, 1984, 2016, 2048, 2112, 2176, 2240, 2304, 2368, 2432,
2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136, 3200,
3264, 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, 3904, 3968,
4032, 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736,
4800, 4864, 4928, 4992, 5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504,
5568, 5632, 5696, 5760, 5824, 5888, 5952, 6016, 6080, 6144 };
/* Calculate Codeblock Segmentation as in Section 5.1.2 of 36.212 */
int srslte_cbsegm(srslte_cbsegm_t *s, uint32_t tbs) {
uint32_t Bp, B, idx1;
int ret;
if (tbs == 0) {
bzero(s, sizeof(srslte_cbsegm_t));
ret = SRSLTE_SUCCESS;
} else {
B = tbs + 24;
s->tbs = tbs;
/* Calculate CB sizes */
if (B <= SRSLTE_TCOD_MAX_LEN_CB) {
s->C = 1;
Bp = B;
} else {
s->C = (uint32_t) ceilf((float) B / (SRSLTE_TCOD_MAX_LEN_CB - 24));
Bp = B + 24 * s->C;
}
ret = srslte_cbsegm_cbindex((Bp-1) / s->C + 1);
if (ret != SRSLTE_ERROR) {
idx1 = (uint32_t) ret;
ret = srslte_cbsegm_cbsize(idx1);
if (ret != SRSLTE_ERROR) {
s->K1 = (uint32_t) ret;
if (idx1 > 0) {
ret = srslte_cbsegm_cbsize(idx1 - 1);
}
if (ret != SRSLTE_ERROR) {
if (s->C == 1) {
s->K2 = 0;
s->C2 = 0;
s->C1 = 1;
} else {
s->K2 = (uint32_t) ret;
s->C2 = (s->C * s->K1 - Bp) / (s->K1 - s->K2);
s->C1 = s->C - s->C2;
}
s->F = s->C1 * s->K1 + s->C2 * s->K2 - Bp;
INFO("CB Segmentation: TBS: %d, C=%d, C+=%d K+=%d, C-=%d, K-=%d, F=%d, Bp=%d\n",
tbs, s->C, s->C1, s->K1, s->C2, s->K2, s->F, Bp);
ret = SRSLTE_SUCCESS;
}
}
}
}
return ret;
}
/*
* Finds index of minimum K>=long_cb in Table 5.1.3-3 of 36.212
*/
int srslte_cbsegm_cbindex(uint32_t long_cb) {
int j = 0;
while (j < SRSLTE_NOF_TC_CB_SIZES && tc_cb_sizes[j] < long_cb) {
j++;
}
if (j == SRSLTE_NOF_TC_CB_SIZES) {
return SRSLTE_ERROR;
} else {
return j;
}
}
/*
* Returns Turbo coder interleaver size for Table 5.1.3-3 (36.212) index
*/
int srslte_cbsegm_cbsize(uint32_t index) {
if (index < SRSLTE_NOF_TC_CB_SIZES) {
return (int) tc_cb_sizes[index];
} else {
return SRSLTE_ERROR;
}
}
bool srslte_cbsegm_cbsize_isvalid(uint32_t size) {
for (int i=0;i<SRSLTE_NOF_TC_CB_SIZES;i++) {
if (tc_cb_sizes[i] == size) {
return true;
}
}
return false;
}

@ -32,6 +32,7 @@
#include "srslte/common/phy_common.h"
#include "srslte/fec/tc_interl.h"
#include "srslte/fec/turbocoder.h"
#include "srslte/fec/cbsegm.h"
#include "srslte/utils/debug.h"
/************************************************
@ -76,7 +77,7 @@ int srslte_tc_interl_LTE_gen(srslte_tc_interl_t *h, uint32_t long_cb) {
return -1;
}
cb_table_idx = srslte_find_cb_index(long_cb);
cb_table_idx = srslte_cbsegm_cbindex(long_cb);
if (cb_table_idx == -1) {
fprintf(stderr, "Can't find long_cb=%d in valid TC CB table\n", long_cb);
return -1;

@ -68,8 +68,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
trblklen = (uint32_t) mxGetScalar(TRBLKLEN);
rvidx = (uint32_t) mxGetScalar(RV);
srslte_harq_cbsegm_t cbsegm;
srslte_harq_codeblock_segmentation(&cbsegm, trblklen);
srslte_cbsegm_t cbsegm;
srslte_cbsegm(&cbsegm, trblklen);
cblen = 3*cbsegm.K1+12;
w_buff_f = calloc(1,sizeof(float) * cblen * 10);

@ -152,7 +152,7 @@ int main(int argc, char **argv) {
if (test_known_data) {
frame_length = KNOWN_DATA_LEN;
} else {
frame_length = srslte_cb_size(srslte_find_cb_index(frame_length));
frame_length = srslte_cbsegm_cbsize(srslte_cbsegm_cbindex(frame_length));
}
coded_length = 3 * (frame_length) + SRSLTE_TCOD_TOTALTAIL;

@ -66,7 +66,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
nof_bits = (nof_symbols-12)/3;
if (!srslte_cb_size_isvalid(nof_bits)) {
if (!srslte_cbsegm_cbsize_isvalid(nof_bits)) {
mexErrMsgTxt("Invalid codeblock size\n");
return;
}

@ -41,23 +41,25 @@
#include "srslte/utils/debug.h"
/* Creates the DL PDSCH resource allocation grant from a DCI message
/* Unpacks a DCI message and configures the DL grant object
*/
int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg, uint16_t msg_rnti,
srslte_cell_t cell, uint32_t cfi,
srslte_ra_pdsch_t *ra_dl)
int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg, uint16_t msg_rnti,
srslte_cell_t cell, uint32_t cfi, uint32_t sf_idx,
srslte_ra_dl_dci_t *dl_dci,
srslte_ra_dl_grant_t *grant)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (msg != NULL &&
ra_dl != NULL &&
srslte_cell_isvalid(&cell) &&
grant != NULL &&
srslte_cell_isvalid(&cell) &&
cfi > 0 &&
cfi < 4)
{
ret = SRSLTE_ERROR;
srslte_dci_msg_type_t type;
if (srslte_dci_msg_get_type(msg, &type, cell.nof_prb, msg_rnti)) {
fprintf(stderr, "Can't get DCI message type\n");
return ret;
@ -68,28 +70,25 @@ int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg, uint16_t msg_rnti,
srslte_dci_msg_type_fprint(stdout, type);
}
if (type.type == SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED) {
bzero(ra_dl, sizeof(srslte_ra_pdsch_t));
bzero(dl_dci, sizeof(srslte_ra_dl_dci_t));
bzero(grant, sizeof(srslte_ra_dl_grant_t));
bool crc_is_crnti = false;
if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) {
crc_is_crnti = true;
}
if (srslte_dci_msg_unpack_pdsch(msg, ra_dl, cell.nof_prb, crc_is_crnti)) {
if (srslte_dci_msg_unpack_pdsch(msg, dl_dci, cell.nof_prb, crc_is_crnti)) {
fprintf(stderr, "Can't unpack PDSCH message\n");
return ret;
}
srslte_ra_dl_dci_to_grant(dl_dci, grant, cell, sf_idx, cfi, crc_is_crnti);
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb);
}
if (srslte_ra_dl_alloc(&ra_dl->prb_alloc, ra_dl, cell.nof_prb)) {
fprintf(stderr, "Error computing resource allocation\n");
return ret;
srslte_ra_pdsch_fprint(stdout, dl_dci, cell.nof_prb);
srslte_ra_dl_grant_fprint(stdout, grant);
}
srslte_ra_dl_alloc_re(&ra_dl->prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
ret = SRSLTE_SUCCESS;
} else {
if (SRSLTE_VERBOSE_ISINFO()) {
@ -103,58 +102,77 @@ int srslte_dci_msg_to_ra_dl(srslte_dci_msg_t *msg, uint16_t msg_rnti,
/* Creates the UL PUSCH resource allocation grant from the random access respone message
*/
int srslte_dci_rar_to_ra_ul(uint32_t rba, uint32_t trunc_mcs, bool hopping_flag, uint32_t nof_prb, srslte_ra_pusch_t *ra) {
bzero(ra, sizeof(srslte_ra_pusch_t));
if (!hopping_flag) {
ra->freq_hop_fl = SRSLTE_RA_PUSCH_HOP_DISABLED;
int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar, srslte_cell_t cell,
uint32_t N_srs, uint32_t n_rb_ho,
srslte_ra_ul_dci_t *ul_dci,
srslte_ra_ul_grant_t *grant)
{
bzero(ul_dci, sizeof(srslte_ra_ul_dci_t));
if (!rar->hopping_flag) {
ul_dci->freq_hop_fl = SRSLTE_RA_PUSCH_HOP_DISABLED;
} else {
fprintf(stderr, "FIXME: Frequency hopping in RAR not implemented\n");
ra->freq_hop_fl = 1;
ul_dci->freq_hop_fl = 1;
}
uint32_t riv = rba;
uint32_t riv = rar->rba;
// Truncate resource block assignment
uint32_t b = 0;
if (nof_prb <= 44) {
b = (uint32_t) (ceilf(log2((float) nof_prb*(nof_prb+1)/2)));
if (cell.nof_prb <= 44) {
b = (uint32_t) (ceilf(log2((float) cell.nof_prb*(cell.nof_prb+1)/2)));
riv = riv & ((1<<(b+1))-1);
}
ra->type2_alloc.riv = riv;
ra->mcs_idx = trunc_mcs;
ul_dci->type2_alloc.riv = riv;
ul_dci->mcs_idx = rar->trunc_mcs;
srslte_ra_type2_from_riv(riv, &ra->type2_alloc.L_crb, &ra->type2_alloc.RB_start,
nof_prb, nof_prb);
srslte_ra_type2_from_riv(riv, &ul_dci->type2_alloc.L_crb, &ul_dci->type2_alloc.RB_start,
cell.nof_prb, cell.nof_prb);
if (srslte_ra_ul_dci_to_grant(ul_dci, grant, cell, n_rb_ho, N_srs)) {
fprintf(stderr, "Error computing resource allocation\n");
return SRSLTE_ERROR;
}
srslte_ra_mcs_from_idx_ul(ra->mcs_idx, srslte_ra_nprb_ul(ra, nof_prb), &ra->mcs);
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, ul_dci, cell.nof_prb);
srslte_ra_ul_grant_fprint(stdout, grant);
}
return SRSLTE_SUCCESS;
}
/* Creates the UL PUSCH resource allocation grant from a DCI format 0 message
*/
int srslte_dci_msg_to_ra_ul(srslte_dci_msg_t *msg, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_pusch_t *ra_ul)
int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, srslte_cell_t cell,
uint32_t N_srs, uint32_t n_rb_ho,
srslte_ra_ul_dci_t *ul_dci,
srslte_ra_ul_grant_t *grant)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (msg != NULL &&
ra_ul != NULL)
srslte_cell_isvalid(&cell) &&
grant != NULL)
{
ret = SRSLTE_ERROR;
bzero(ra_ul, sizeof(srslte_ra_pusch_t));
bzero(ul_dci, sizeof(srslte_ra_ul_dci_t));
bzero(grant, sizeof(srslte_ra_ul_dci_t));
if (srslte_dci_msg_unpack_pusch(msg, ra_ul, nof_prb)) {
if (srslte_dci_msg_unpack_pusch(msg, ul_dci, cell.nof_prb)) {
fprintf(stderr, "Can't unpack PDSCH message\n");
return ret;
}
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, ra_ul, nof_prb);
}
if (srslte_ra_ul_alloc(&ra_ul->prb_alloc, ra_ul, n_rb_ho, nof_prb)) {
if (srslte_ra_ul_dci_to_grant(ul_dci, grant, cell, n_rb_ho, N_srs)) {
fprintf(stderr, "Error computing resource allocation\n");
return ret;
}
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, ul_dci, cell.nof_prb);
srslte_ra_ul_grant_fprint(stdout, grant);
}
ret = SRSLTE_SUCCESS;
}
return ret;
@ -275,7 +293,7 @@ uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format, uint32_t nof_prb)
*
* TODO: TPC and cyclic shift for DM RS not implemented
*/
int dci_format0_pack(srslte_ra_pusch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
int dci_format0_pack(srslte_ra_ul_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
/* pack bits */
uint8_t *y = msg->data;
@ -337,7 +355,7 @@ int dci_format0_pack(srslte_ra_pusch_t *data, srslte_dci_msg_t *msg, uint32_t no
*
* TODO: TPC and cyclic shift for DM RS not implemented
*/
int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t nof_prb) {
int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_ul_dci_t *data, uint32_t nof_prb) {
/* pack bits */
uint8_t *y = msg->data;
@ -384,19 +402,6 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t
// CQI request
data->cqi_request = *y++ ? true : false;
// 8.6.2 First paragraph
if (data->mcs_idx <= 28) {
srslte_ra_mcs_from_idx_ul(data->mcs_idx, srslte_ra_nprb_ul(data, nof_prb), &data->mcs);
} else if (data->mcs_idx == 29 && data->cqi_request && srslte_ra_nprb_ul(data, nof_prb) <= 4) {
// 8.6.1 and 8.6.2 36.213 second paragraph
data->mcs.mod = SRSLTE_MOD_QPSK;
data->mcs.tbs = 0;
} else if (data->mcs_idx >= 29) {
// Else leave TBS and use the previously used PUSCH modulation
data->mcs.tbs = 0;
data->rv_idx = data->mcs_idx - 28;
}
return SRSLTE_SUCCESS;
}
@ -406,7 +411,7 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t
* TODO: TPC commands
*/
int dci_format1_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
int dci_format1_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
/* pack bits */
uint8_t *y = msg->data;
@ -459,7 +464,7 @@ int dci_format1_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t no
return SRSLTE_SUCCESS;
}
int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t nof_prb) {
int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb) {
/* pack bits */
uint8_t *y = msg->data;
@ -496,10 +501,6 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t
}
/* unpack MCS according to 7.1.7 of 36.213 */
data->mcs_idx = srslte_bit_unpack(&y, 5);
if (srslte_ra_mcs_from_idx_dl(data->mcs_idx, srslte_ra_nprb_dl(data, nof_prb), &data->mcs)) {
fprintf(stderr, "Error getting MCS\n");
return SRSLTE_ERROR;
}
/* harq process number */
data->harq_process = srslte_bit_unpack(&y, 3);
@ -510,6 +511,9 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t
data->rv_idx = srslte_bit_unpack(&y, 2);
// TPC not implemented
data->dci_format = SRSLTE_RA_DCI_FORMAT1;
return SRSLTE_SUCCESS;
}
@ -518,7 +522,7 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t
*
* TODO: RA procedure initiated by PDCCH, TPC commands
*/
int dci_format1As_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb,
int dci_format1As_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb,
bool crc_is_crnti) {
/* pack bits */
@ -604,7 +608,7 @@ int dci_format1As_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t
/* Unpacks DCI format 1A for compact scheduling of PDSCH words according to 36.212 5.3.3.1.3
*
*/
int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t nof_prb,
int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb,
bool crc_is_crnti) {
/* pack bits */
@ -667,14 +671,7 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_
data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS
}
uint32_t n_prb;
if (crc_is_crnti) {
n_prb = srslte_ra_nprb_dl(data, nof_prb);
} else {
n_prb = data->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3;
}
data->mcs.tbs = srslte_ra_tbs_from_idx(data->mcs_idx, n_prb);
data->mcs.mod = SRSLTE_MOD_QPSK;
data->dci_format = SRSLTE_RA_DCI_FORMAT1A;
return SRSLTE_SUCCESS;
}
@ -682,7 +679,7 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_
/* Format 1C for compact scheduling of PDSCH words
*
*/
int dci_format1Cs_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
int dci_format1Cs_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
/* pack bits */
uint8_t *y = msg->data;
@ -732,7 +729,7 @@ int dci_format1Cs_pack(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, uint32_t
return SRSLTE_SUCCESS;
}
int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t nof_prb) {
int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb) {
uint32_t L_p, RB_p;
/* pack bits */
@ -759,15 +756,15 @@ int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_
data->type2_alloc.riv = riv;
data->mcs_idx = srslte_bit_unpack(&y, 5);
data->mcs.tbs = srslte_ra_tbs_from_idx_format1c(data->mcs_idx);
data->mcs.mod = SRSLTE_MOD_QPSK;
data->dci_format = SRSLTE_RA_DCI_FORMAT1C;
msg->nof_bits = (y - msg->data);
return SRSLTE_SUCCESS;
}
int srslte_dci_msg_pack_pdsch(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, srslte_dci_format_t format,
int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, srslte_dci_format_t format,
uint32_t nof_prb, bool crc_is_crnti) {
switch (format) {
case SRSLTE_DCI_FORMAT1:
@ -783,7 +780,7 @@ int srslte_dci_msg_pack_pdsch(srslte_ra_pdsch_t *data, srslte_dci_msg_t *msg, sr
}
}
int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t nof_prb,
int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb,
bool crc_is_crnti) {
if (msg->nof_bits == srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, nof_prb)) {
return dci_format1_unpack(msg, data, nof_prb);
@ -796,11 +793,11 @@ int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data,
}
}
int srslte_dci_msg_pack_pusch(srslte_ra_pusch_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
int srslte_dci_msg_pack_pusch(srslte_ra_ul_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
return dci_format0_pack(data, msg, nof_prb);
}
int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg, srslte_ra_pusch_t *data, uint32_t nof_prb) {
int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg, srslte_ra_ul_dci_t *data, uint32_t nof_prb) {
return dci_format0_unpack(msg, data, nof_prb);
}

@ -1,248 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include "srslte/common/phy_common.h"
#include "srslte/phch/ra.h"
#include "srslte/phch/harq.h"
#include "srslte/fec/turbodecoder.h"
#include "srslte/utils/vector.h"
#include "srslte/utils/debug.h"
#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
/* Calculate Codeblock Segmentation as in Section 5.1.2 of 36.212 */
int srslte_harq_codeblock_segmentation(srslte_harq_cbsegm_t *s, uint32_t tbs) {
uint32_t Bp, B, idx1;
int ret;
if (tbs == 0) {
bzero(s, sizeof(srslte_harq_cbsegm_t));
ret = SRSLTE_SUCCESS;
} else {
B = tbs + 24;
/* Calculate CB sizes */
if (B <= MAX_LONG_CB) {
s->C = 1;
Bp = B;
} else {
s->C = (uint32_t) ceilf((float) B / (MAX_LONG_CB - 24));
Bp = B + 24 * s->C;
}
ret = srslte_find_cb_index((Bp-1) / s->C + 1);
if (ret != SRSLTE_ERROR) {
idx1 = (uint32_t) ret;
ret = srslte_cb_size(idx1);
if (ret != SRSLTE_ERROR) {
s->K1 = (uint32_t) ret;
if (idx1 > 0) {
ret = srslte_cb_size(idx1 - 1);
}
if (ret != SRSLTE_ERROR) {
if (s->C == 1) {
s->K2 = 0;
s->C2 = 0;
s->C1 = 1;
} else {
s->K2 = (uint32_t) ret;
s->C2 = (s->C * s->K1 - Bp) / (s->K1 - s->K2);
s->C1 = s->C - s->C2;
}
s->F = s->C1 * s->K1 + s->C2 * s->K2 - Bp;
INFO("CB Segmentation: TBS: %d, C=%d, C+=%d K+=%d, C-=%d, K-=%d, F=%d, Bp=%d\n",
tbs, s->C, s->C1, s->K1, s->C2, s->K2, s->F, Bp);
}
}
}
}
return ret;
}
int srslte_harq_init(srslte_harq_t *q, srslte_cell_t cell) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
uint32_t i;
bzero(q, sizeof(srslte_harq_t));
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
ret = srslte_ra_tbs_from_idx(26, cell.nof_prb);
if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (MAX_LONG_CB - 24) + 1;
q->pdsch_w_buff_f = srslte_vec_malloc(sizeof(float*) * q->max_cb);
if (!q->pdsch_w_buff_f) {
perror("malloc");
return SRSLTE_ERROR;
}
q->pdsch_w_buff_c = srslte_vec_malloc(sizeof(uint8_t*) * q->max_cb);
if (!q->pdsch_w_buff_c) {
perror("malloc");
return SRSLTE_ERROR;
}
// FIXME: Use HARQ buffer limitation based on UE category
q->w_buff_size = cell.nof_prb * MAX_PDSCH_RE(cell.cp) * 6 * 10;
for (i=0;i<q->max_cb;i++) {
q->pdsch_w_buff_f[i] = srslte_vec_malloc(sizeof(float) * q->w_buff_size);
if (!q->pdsch_w_buff_f[i]) {
perror("malloc");
return SRSLTE_ERROR;
}
q->pdsch_w_buff_c[i] = srslte_vec_malloc(sizeof(uint8_t) * q->w_buff_size);
if (!q->pdsch_w_buff_c[i]) {
perror("malloc");
return SRSLTE_ERROR;
}
bzero(q->pdsch_w_buff_c[i], sizeof(uint8_t) * q->w_buff_size);
}
ret = SRSLTE_SUCCESS;
}
}
return ret;
}
void srslte_harq_free(srslte_harq_t *q) {
if (q) {
uint32_t i;
if (q->pdsch_w_buff_f) {
for (i=0;i<q->max_cb;i++) {
if (q->pdsch_w_buff_f[i]) {
free(q->pdsch_w_buff_f[i]);
}
}
free(q->pdsch_w_buff_f);
}
if (q->pdsch_w_buff_c) {
for (i=0;i<q->max_cb;i++) {
if (q->pdsch_w_buff_c[i]) {
free(q->pdsch_w_buff_c[i]);
}
}
free(q->pdsch_w_buff_c);
}
bzero(q, sizeof(srslte_harq_t));
}
}
void srslte_harq_reset(srslte_harq_t *q) {
int i;
if (q->pdsch_w_buff_f) {
for (i=0;i<q->max_cb;i++) {
if (q->pdsch_w_buff_f[i]) {
bzero(q->pdsch_w_buff_f[i], sizeof(float) * q->w_buff_size);
}
}
}
if (q->pdsch_w_buff_c) {
for (i=0;i<q->max_cb;i++) {
if (q->pdsch_w_buff_c[i]) {
bzero(q->pdsch_w_buff_c[i], sizeof(uint8_t) * q->w_buff_size);
}
}
}
bzero(&q->mcs, sizeof(srslte_ra_mcs_t));
bzero(&q->cb_segm, sizeof(srslte_harq_cbsegm_t));
bzero(&q->dl_alloc, sizeof(srslte_ra_dl_alloc_t));
}
static int harq_setup_common(srslte_harq_t *q, srslte_ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx) {
if (mcs.tbs != q->mcs.tbs) {
srslte_harq_codeblock_segmentation(&q->cb_segm, mcs.tbs);
if (q->cb_segm.C > q->max_cb) {
fprintf(stderr, "Codeblock segmentation returned more CBs (%d) than allocated (%d)\n",
q->cb_segm.C, q->max_cb);
return SRSLTE_ERROR;
}
}
q->mcs = mcs;
q->sf_idx = sf_idx;
q->rv = rv;
return SRSLTE_SUCCESS;
}
int srslte_harq_setup_dl(srslte_harq_t *q, srslte_ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, srslte_ra_dl_alloc_t *dl_alloc) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
rv < 4 &&
sf_idx < 10)
{
ret = harq_setup_common(q, mcs, rv, sf_idx);
if (ret) {
return ret;
}
memcpy(&q->dl_alloc, dl_alloc, sizeof(srslte_ra_dl_alloc_t));
// Number of symbols, RE and bits per subframe for DL
q->nof_re = q->dl_alloc.re_sf[q->sf_idx];
q->nof_symb = 2*SRSLTE_CP_NSYMB(q->cell.cp)-q->dl_alloc.lstart;
q->nof_bits = q->nof_re * srslte_mod_bits_x_symbol(q->mcs.mod);
q->nof_prb = q->dl_alloc.slot[0].nof_prb;
ret = SRSLTE_SUCCESS;
}
return ret;
}
int srslte_harq_setup_ul(srslte_harq_t *q, srslte_ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, srslte_ra_ul_alloc_t *ul_alloc) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
rv < 4 &&
sf_idx < 10)
{
ret = harq_setup_common(q, mcs, rv, sf_idx);
if (ret) {
return ret;
}
memcpy(&q->ul_alloc, ul_alloc, sizeof(srslte_ra_ul_alloc_t));
// Number of symbols, RE and bits per subframe for UL
q->nof_symb = 2*(SRSLTE_CP_NSYMB(q->cell.cp)-1);
q->nof_re = q->nof_symb*q->ul_alloc.L_prb*SRSLTE_NRE;
q->nof_bits = q->nof_re * srslte_mod_bits_x_symbol(q->mcs.mod);
q->nof_prb = q->ul_alloc.L_prb;
ret = SRSLTE_SUCCESS;
}
return ret;
}

@ -36,6 +36,7 @@
#include "prb_dl.h"
#include "srslte/phch/pdsch.h"
#include "srslte/phch/sch.h"
#include "srslte/common/phy_common.h"
#include "srslte/utils/bit.h"
#include "srslte/utils/debug.h"
@ -58,7 +59,7 @@ extern int indices_ptr;
#endif
int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_alloc_t *prb_alloc,
int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant,
uint32_t nsubframe, bool put) {
uint32_t s, n, l, lp, lstart, lend, nof_refs;
bool is_pbch, is_sss;
@ -66,7 +67,7 @@ int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_a
uint32_t offset = 0;
INFO("%s %d RE from %d PRB\n", put ? "Putting" : "Getting",
prb_alloc->re_sf[nsubframe], prb_alloc->slot[0].nof_prb);
grant->nof_re, grant->nof_prb);
#ifdef DEBUG_IDX
indices_ptr = 0;
@ -88,9 +89,9 @@ int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_a
for (n = 0; n < q->cell.nof_prb; n++) {
// If this PRB is assigned
if (prb_alloc->slot[s].prb_idx[n]) {
if (grant->prb_idx[s][n]) {
if (s == 0) {
lstart = prb_alloc->lstart;
lstart = grant->lstart;
} else {
lstart = 0;
}
@ -179,8 +180,8 @@ int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_a
* 36.211 10.3 section 6.3.5
*/
int srslte_pdsch_put(srslte_pdsch_t *q, cf_t *symbols, cf_t *sf_symbols,
srslte_ra_dl_alloc_t *prb_alloc, uint32_t subframe) {
return srslte_pdsch_cp(q, symbols, sf_symbols, prb_alloc, subframe, true);
srslte_ra_dl_grant_t *grant, uint32_t subframe) {
return srslte_pdsch_cp(q, symbols, sf_symbols, grant, subframe, true);
}
/**
@ -191,8 +192,8 @@ int srslte_pdsch_put(srslte_pdsch_t *q, cf_t *symbols, cf_t *sf_symbols,
* 36.211 10.3 section 6.3.5
*/
int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols,
srslte_ra_dl_alloc_t *prb_alloc, uint32_t subframe) {
return srslte_pdsch_cp(q, sf_symbols, symbols, prb_alloc, subframe, false);
srslte_ra_dl_grant_t *grant, uint32_t subframe) {
return srslte_pdsch_cp(q, sf_symbols, symbols, grant, subframe, false);
}
/** Initializes the PDCCH transmitter and receiver */
@ -318,14 +319,18 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
return SRSLTE_SUCCESS;
}
int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, uint8_t *data) {
int srslte_pdsch_decode(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate,
uint8_t *data)
{
if (q != NULL &&
sf_symbols != NULL &&
data != NULL &&
harq != NULL)
cfg != NULL)
{
if (q->rnti_is_set) {
return srslte_pdsch_decode_rnti(q, harq, sf_symbols, ce, noise_estimate, q->rnti, data);
return srslte_pdsch_decode_rnti(q, cfg, softbuffer, sf_symbols, ce, noise_estimate, q->rnti, data);
} else {
fprintf(stderr, "Must call srslte_pdsch_set_rnti() before calling srslte_pdsch_decode()\n");
return SRSLTE_ERROR;
@ -337,22 +342,30 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_symbols
/** Decodes the PDSCH from the received symbols
*/
int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate, uint16_t rnti, uint8_t *data)
int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate,
uint16_t rnti, uint8_t *data)
{
/* Set pointers for layermapping & precoding */
uint32_t i, n;
cf_t *x[SRSLTE_MAX_LAYERS];
if (q != NULL &&
sf_symbols != NULL &&
data != NULL &&
harq != NULL)
if (q != NULL &&
sf_symbols != NULL &&
data != NULL &&
cfg != NULL)
{
INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
harq->sf_idx, rnti, srslte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
cfg->sf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->grant.nof_re,
cfg->grant.nof_bits, cfg->rv);
if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) {
fprintf(stderr, "Invalid code rate %d/%d=%.2f\n", cfg->grant.mcs.tbs, cfg->grant.nof_bits, (float) cfg->grant.mcs.tbs / cfg->grant.nof_bits);
return SRSLTE_ERROR_INVALID_INPUTS;
}
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {
@ -361,17 +374,17 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_sy
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
/* extract symbols */
n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &harq->dl_alloc, harq->sf_idx);
if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &cfg->grant, cfg->sf_idx);
if (n != cfg->grant.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n);
return SRSLTE_ERROR;
}
/* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) {
n = srslte_pdsch_get(q, ce[i], q->ce[i], &harq->dl_alloc, harq->sf_idx);
if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
n = srslte_pdsch_get(q, ce[i], q->ce[i], &cfg->grant, cfg->sf_idx);
if (n != cfg->grant.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n);
return SRSLTE_ERROR;
}
}
@ -380,12 +393,12 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_sy
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
srslte_predecoding_single(&q->precoding, q->symbols[0], q->ce[0], q->d,
harq->nof_re, noise_estimate);
cfg->grant.nof_re, noise_estimate);
} else {
srslte_predecoding_diversity(&q->precoding, q->symbols[0], q->ce, x, q->cell.nof_ports,
harq->nof_re, noise_estimate);
cfg->grant.nof_re, noise_estimate);
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports,
harq->nof_re / q->cell.nof_ports);
cfg->grant.nof_re / q->cell.nof_ports);
}
/* demodulate symbols
@ -393,36 +406,38 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, cf_t *sf_sy
* thus we don't need tot set it in the LLRs normalization
*/
srslte_demod_soft_sigma_set(&q->demod, sqrt(0.5));
srslte_demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]);
srslte_demod_soft_demodulate(&q->demod, q->d, q->e, harq->nof_re);
srslte_demod_soft_table_set(&q->demod, &q->mod[cfg->grant.mcs.mod]);
srslte_demod_soft_demodulate(&q->demod, q->d, q->e, cfg->grant.nof_re);
/* descramble */
if (rnti != q->rnti) {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) {
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->grant.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_f_offset(&seq, q->e, 0, harq->nof_bits);
srslte_scrambling_f_offset(&seq, q->e, 0, cfg->grant.nof_bits);
srslte_sequence_free(&seq);
} else {
srslte_scrambling_f_offset(&q->seq[harq->sf_idx], q->e, 0, harq->nof_bits);
srslte_scrambling_f_offset(&q->seq[cfg->sf_idx], q->e, 0, cfg->grant.nof_bits);
}
return srslte_dlsch_decode(&q->dl_sch, harq, q->e, data);
return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data);
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
int srslte_pdsch_encode(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *data, cf_t *sf_symbols[SRSLTE_MAX_PORTS])
int srslte_pdsch_encode(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, cf_t *sf_symbols[SRSLTE_MAX_PORTS])
{
if (q != NULL &&
data != NULL &&
harq != NULL)
if (q != NULL &&
data != NULL &&
cfg != NULL)
{
if (q->rnti_is_set) {
return srslte_pdsch_encode_rnti(q, harq, data, q->rnti, sf_symbols);
return srslte_pdsch_encode_rnti(q, cfg, softbuffer, data, q->rnti, sf_symbols);
} else {
fprintf(stderr, "Must call srslte_pdsch_set_rnti() to set the encoder/decoder RNTI\n");
return SRSLTE_ERROR;
@ -434,7 +449,9 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *data, c
/** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission
*/
int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS])
int srslte_pdsch_encode_rnti(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS])
{
int i;
/* Set pointers for layermapping & precoding */
@ -443,7 +460,7 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *da
if (q != NULL &&
data != NULL &&
harq != NULL)
cfg != NULL)
{
for (i=0;i<q->cell.nof_ports;i++) {
@ -452,24 +469,25 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *da
}
}
if (harq->mcs.tbs == 0) {
if (cfg->grant.mcs.tbs == 0) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (harq->mcs.tbs > harq->nof_bits) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits);
if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) {
fprintf(stderr, "Invalid code rate %d/%d=%.2f\n", cfg->grant.mcs.tbs, cfg->grant.nof_bits, (float) cfg->grant.mcs.tbs / cfg->grant.nof_bits);
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (harq->nof_re > q->max_re) {
if (cfg->grant.nof_re > q->max_re) {
fprintf(stderr,
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n",
harq->nof_re, q->max_re, q->cell.nof_prb);
cfg->grant.nof_re, q->max_re, q->cell.nof_prb);
return SRSLTE_ERROR_INVALID_INPUTS;
}
INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
harq->sf_idx, srslte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs,
cfg->grant.nof_re, cfg->grant.nof_bits, cfg->rv);
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {
@ -477,36 +495,36 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_harq_t *harq, uint8_t *da
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
if (srslte_dlsch_encode(&q->dl_sch, harq, data, q->e)) {
if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) {
fprintf(stderr, "Error encoding TB\n");
return SRSLTE_ERROR;
}
if (rnti != q->rnti) {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) {
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->grant.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_b_offset(&seq, (uint8_t*) q->e, 0, harq->nof_bits);
srslte_scrambling_b_offset(&seq, (uint8_t*) q->e, 0, cfg->grant.nof_bits);
srslte_sequence_free(&seq);
} else {
srslte_scrambling_b_offset(&q->seq[harq->sf_idx], (uint8_t*) q->e, 0, harq->nof_bits);
srslte_scrambling_b_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->e, 0, cfg->grant.nof_bits);
}
srslte_mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->e, q->d, harq->nof_bits);
srslte_mod_modulate(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->grant.nof_bits);
/* TODO: only diversity supported */
if (q->cell.nof_ports > 1) {
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, harq->nof_re);
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, cfg->grant.nof_re);
srslte_precoding_diversity(&q->precoding, x, q->symbols, q->cell.nof_ports,
harq->nof_re / q->cell.nof_ports);
cfg->grant.nof_re / q->cell.nof_ports);
} else {
memcpy(q->symbols[0], q->d, harq->nof_re * sizeof(cf_t));
memcpy(q->symbols[0], q->d, cfg->grant.nof_re * sizeof(cf_t));
}
/* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) {
srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &harq->dl_alloc, harq->sf_idx);
srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->sf_idx);
}
ret = SRSLTE_SUCCESS;
}

@ -35,6 +35,7 @@
#include <math.h>
#include "srslte/phch/pusch.h"
#include "srslte/phch/pusch_cfg.h"
#include "srslte/phch/uci.h"
#include "srslte/common/phy_common.h"
#include "srslte/utils/bit.h"
@ -83,7 +84,7 @@ static int f_m(srslte_pusch_t *q, srslte_pusch_hopping_cfg_t *hopping, uint32_t
}
}
int pusch_cp(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output, bool advance_input)
int pusch_cp(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, uint32_t sf_idx, cf_t *input, cf_t *output, bool advance_input)
{
cf_t *in_ptr = input;
cf_t *out_ptr = output;
@ -93,27 +94,27 @@ int pusch_cp(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output,
if (SRSLTE_CP_ISEXT(q->cell.cp)) {
L_ref = 2;
}
INFO("PUSCH Freq hopping: %d\n", harq->ul_alloc.freq_hopping);
INFO("PUSCH Freq hopping: %d\n", grant->freq_hopping);
for (uint32_t slot=0;slot<2;slot++) {
uint32_t n_prb_tilde = harq->ul_alloc.n_prb[slot];
if (harq->ul_alloc.freq_hopping == 1) {
uint32_t n_prb_tilde = grant->n_prb[slot];
if (grant->freq_hopping == 1) {
if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) {
n_prb_tilde = harq->ul_alloc.n_prb[hopping->current_tx_nb%2];
n_prb_tilde = grant->n_prb[hopping->current_tx_nb%2];
} else {
n_prb_tilde = harq->ul_alloc.n_prb[slot];
n_prb_tilde = grant->n_prb[slot];
}
}
if (harq->ul_alloc.freq_hopping == 2) {
if (grant->freq_hopping == 2) {
/* Freq hopping type 2 as defined in 5.3.4 of 36.211 */
uint32_t n_vrb_tilde = harq->ul_alloc.n_prb[0];
uint32_t n_vrb_tilde = grant->n_prb[0];
if (hopping->n_sb > 1) {
n_vrb_tilde -= (hopping->hopping_offset-1)/2+1;
}
int i=0;
if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) {
i = harq->sf_idx;
i = sf_idx;
} else {
i = 2*harq->sf_idx+slot;
i = 2*sf_idx+slot;
}
uint32_t n_rb_sb = q->cell.nof_prb;
if (hopping->n_sb > 1) {
@ -129,8 +130,8 @@ int pusch_cp(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output,
}
}
harq->ul_alloc.n_prb_tilde[slot] = n_prb_tilde;
INFO("Allocating PUSCH %d PRB to index %d at slot %d\n",harq->ul_alloc.L_prb, n_prb_tilde,slot);
grant->n_prb_tilde[slot] = n_prb_tilde;
INFO("Allocating PUSCH %d PRB to index %d at slot %d\n",grant->L_prb, n_prb_tilde,slot);
for (uint32_t l=0;l<SRSLTE_CP_NSYMB(q->cell.cp);l++) {
if (l != L_ref) {
uint32_t idx = SRSLTE_RE_IDX(q->cell.nof_prb, l+slot*SRSLTE_CP_NSYMB(q->cell.cp),
@ -140,24 +141,24 @@ int pusch_cp(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output,
} else {
in_ptr = &input[idx];
}
memcpy(out_ptr, in_ptr, harq->ul_alloc.L_prb * SRSLTE_NRE * sizeof(cf_t));
memcpy(out_ptr, in_ptr, grant->L_prb * SRSLTE_NRE * sizeof(cf_t));
if (advance_input) {
in_ptr += harq->ul_alloc.L_prb*SRSLTE_NRE;
in_ptr += grant->L_prb*SRSLTE_NRE;
} else {
out_ptr += harq->ul_alloc.L_prb*SRSLTE_NRE;
out_ptr += grant->L_prb*SRSLTE_NRE;
}
}
}
}
return SRSLTE_NRE*harq->ul_alloc.L_prb;
return SRSLTE_NRE*grant->L_prb;
}
int pusch_put(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output) {
return pusch_cp(q, harq, input, output, true);
int pusch_put(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, uint32_t sf_idx, cf_t *input, cf_t *output) {
return pusch_cp(q, grant, sf_idx, input, output, true);
}
int get(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output) {
return pusch_cp(q, harq, input, output, false);
int pusch_get(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, uint32_t sf_idx, cf_t *input, cf_t *output) {
return pusch_cp(q, grant, sf_idx, input, output, false);
}
@ -306,53 +307,57 @@ int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) {
/** Decodes the PUSCH from the received symbols
*/
int srslte_pusch_decode(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint8_t *data)
int srslte_pusch_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)
{
uint32_t n;
if (q != NULL &&
sf_symbols != NULL &&
data != NULL &&
harq != NULL)
if (q != NULL &&
sf_symbols != NULL &&
data != NULL &&
cfg != NULL)
{
if (q->rnti_is_set) {
INFO("Decoding PUSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
harq->sf_idx, srslte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs,
cfg->grant.nof_re, cfg->grant.nof_bits, cfg->rv);
/* extract symbols */
n = get(q, harq, sf_symbols, q->d);
if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
n = pusch_get(q, &cfg->grant, cfg->sf_idx, sf_symbols, q->d);
if (n != cfg->grant.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n);
return SRSLTE_ERROR;
}
/* extract channel estimates */
n = get(q, harq, ce, q->ce);
if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
n = pusch_get(q, &cfg->grant, cfg->sf_idx, ce, q->ce);
if (n != cfg->grant.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n);
return SRSLTE_ERROR;
}
srslte_predecoding_single(&q->equalizer, q->d, q->ce, q->z,
harq->nof_re, noise_estimate);
cfg->grant.nof_re, noise_estimate);
srslte_dft_predecoding(&q->dft_precoding, q->z, q->d,
harq->ul_alloc.L_prb, harq->nof_symb);
srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->grant.nof_symb);
/* demodulate symbols
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
srslte_demod_soft_sigma_set(&q->demod, sqrt(0.5));
srslte_demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]);
srslte_demod_soft_demodulate(&q->demod, q->d, q->q, harq->nof_re);
srslte_demod_soft_table_set(&q->demod, &q->mod[cfg->grant.mcs.mod]);
srslte_demod_soft_demodulate(&q->demod, q->d, q->q, cfg->grant.nof_re);
/* descramble */
srslte_scrambling_f_offset(&q->seq[harq->sf_idx], q->q, 0, harq->nof_bits);
srslte_scrambling_f_offset(&q->seq[cfg->sf_idx], q->q, 0, cfg->grant.nof_bits);
return srslte_ulsch_decode(&q->dl_sch, harq, q->q, data);
return srslte_ulsch_decode(&q->dl_sch, cfg, softbuffer, q->q, data);
} else {
fprintf(stderr, "Must call srslte_pusch_set_rnti() before calling srslte_pusch_decode()\n");
return SRSLTE_ERROR;
@ -362,29 +367,34 @@ int srslte_pusch_decode(srslte_pusch_t *q, srslte_harq_t *harq, cf_t *sf_symbols
}
}
int srslte_pusch_encode_rnti(srslte_pusch_t *q, srslte_harq_t *harq_process, uint8_t *data, uint16_t rnti, cf_t *sf_symbols)
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,
cf_t *sf_symbols)
{
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return srslte_pusch_uci_encode_rnti(q, harq_process, data, uci_data, rnti, sf_symbols);
return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, rnti, sf_symbols);
}
int srslte_pusch_encode(srslte_pusch_t *q, srslte_harq_t *harq_process, uint8_t *data, cf_t *sf_symbols)
int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, cf_t *sf_symbols)
{
if (q->rnti_is_set) {
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return srslte_pusch_uci_encode_rnti(q, harq_process, data, uci_data, q->rnti, sf_symbols);
return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, q->rnti, sf_symbols);
} else {
fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n");
return SRSLTE_ERROR;
}
}
int srslte_pusch_uci_encode(srslte_pusch_t *q, srslte_harq_t *harq, uint8_t *data, srslte_uci_data_t uci_data, cf_t *sf_symbols)
int srslte_pusch_uci_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, srslte_uci_data_t uci_data,
cf_t *sf_symbols)
{
if (q->rnti_is_set) {
return srslte_pusch_uci_encode_rnti(q, harq, data, uci_data, q->rnti, sf_symbols);
return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, q->rnti, sf_symbols);
} else {
fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n");
return SRSLTE_ERROR;
@ -393,52 +403,54 @@ int srslte_pusch_uci_encode(srslte_pusch_t *q, srslte_harq_t *harq, uint8_t *dat
/** Converts the PUSCH data bits to symbols mapped to the slot ready for transmission
*/
int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_harq_t *harq, uint8_t *data, srslte_uci_data_t uci_data, uint16_t rnti, cf_t *sf_symbols)
int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, srslte_uci_data_t uci_data, uint16_t rnti,
cf_t *sf_symbols)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
data != NULL &&
harq != NULL)
cfg != NULL)
{
if (harq->mcs.tbs > harq->nof_bits) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits);
if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) cfg->grant.mcs.tbs / cfg->grant.nof_bits);
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (harq->nof_re > q->max_re) {
if (cfg->grant.nof_re > q->max_re) {
fprintf(stderr, "Error too many RE per subframe (%d). PUSCH configured for %d RE (%d PRB)\n",
harq->nof_re, q->max_re, q->cell.nof_prb);
cfg->grant.nof_re, q->max_re, q->cell.nof_prb);
return SRSLTE_ERROR_INVALID_INPUTS;
}
INFO("Encoding PUSCH SF: %d, Mod %s, RNTI: %d, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
harq->sf_idx, srslte_mod_string(harq->mcs.mod), rnti, harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), rnti,
cfg->grant.mcs.tbs, cfg->grant.nof_re, cfg->grant.nof_bits, cfg->rv);
bzero(q->q, harq->nof_bits);
if (srslte_ulsch_uci_encode(&q->dl_sch, harq, data, uci_data, q->g, q->q)) {
bzero(q->q, cfg->grant.nof_bits);
if (srslte_ulsch_uci_encode(&q->dl_sch, cfg, softbuffer, data, uci_data, q->g, q->q)) {
fprintf(stderr, "Error encoding TB\n");
return SRSLTE_ERROR;
}
if (rnti != q->rnti) {
srslte_sequence_t seq;
if (srslte_sequence_pusch(&seq, rnti, 2 * harq->sf_idx, q->cell.id, harq->nof_bits)) {
if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->grant.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_b_offset_pusch(&seq, (uint8_t*) q->q, 0, harq->nof_bits);
srslte_scrambling_b_offset_pusch(&seq, (uint8_t*) q->q, 0, cfg->grant.nof_bits);
srslte_sequence_free(&seq);
} else {
srslte_scrambling_b_offset_pusch(&q->seq[harq->sf_idx], (uint8_t*) q->q, 0, harq->nof_bits);
srslte_scrambling_b_offset_pusch(&q->seq[cfg->sf_idx], (uint8_t*) q->q, 0, cfg->grant.nof_bits);
}
srslte_mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->q, q->d, harq->nof_bits);
srslte_mod_modulate(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->q, q->d, cfg->grant.nof_bits);
srslte_dft_precoding(&q->dft_precoding, q->d, q->z,
harq->ul_alloc.L_prb, harq->nof_symb);
srslte_dft_precoding(&q->dft_precoding, q->d, q->z, cfg->grant.L_prb, cfg->grant.nof_symb);
/* mapping to resource elements */
pusch_put(q, harq, q->z, sf_symbols);
pusch_put(q, &cfg->grant, cfg->sf_idx, q->z, sf_symbols);
ret = SRSLTE_SUCCESS;
}

@ -108,44 +108,30 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_
return re;
}
void srslte_ra_prb_fprint(FILE *f, srslte_ra_prb_slot_t *prb, uint32_t nof_prb) {
int i;
if (prb->nof_prb > 0) {
for (i=0;i<nof_prb;i++) {
if (prb->prb_idx[i]) {
fprintf(f, "%d, ", i);
}
}
fprintf(f, "\n");
}
}
/** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */
int srslte_ra_ul_alloc(srslte_ra_ul_alloc_t *prb_dist, srslte_ra_pusch_t *ra, uint32_t n_rb_ho, uint32_t nof_prb) {
bzero(prb_dist, sizeof(srslte_ra_ul_alloc_t));
prb_dist->L_prb = ra->type2_alloc.L_crb;
uint32_t n_prb_1 = ra->type2_alloc.RB_start;
int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant,
uint32_t n_rb_ho, uint32_t nof_prb) {
bzero(grant, sizeof(srslte_ra_ul_grant_t));
grant->L_prb = dci->type2_alloc.L_crb;
uint32_t n_prb_1 = dci->type2_alloc.RB_start;
uint32_t n_rb_pusch = 0;
if (n_rb_ho%2) {
n_rb_ho++;
}
if (ra->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED || ra->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_TYPE2) {
if (dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED || dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_TYPE2) {
/* For no freq hopping or type2 freq hopping, n_prb is the same
* n_prb_tilde is calculated during resource mapping
*/
for (uint32_t i=0;i<2;i++) {
prb_dist->n_prb[i] = n_prb_1;
grant->n_prb[i] = n_prb_1;
}
if (ra->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) {
prb_dist->freq_hopping = 0;
if (dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) {
grant->freq_hopping = 0;
} else {
prb_dist->freq_hopping = 2;
grant->freq_hopping = 2;
}
INFO("prb1: %d, prb2: %d, L: %d\n", prb_dist->n_prb[0], prb_dist->n_prb[1], prb_dist->L_prb);
INFO("prb1: %d, prb2: %d, L: %d\n", grant->n_prb[0], grant->n_prb[1], grant->L_prb);
} else {
/* Type1 frequency hopping as defined in 8.4.1 of 36.213
* frequency offset between 1st and 2nd slot is fixed.
@ -153,108 +139,166 @@ int srslte_ra_ul_alloc(srslte_ra_ul_alloc_t *prb_dist, srslte_ra_pusch_t *ra, ui
n_rb_pusch = nof_prb - n_rb_ho - (nof_prb%2);
// starting prb idx for slot 0 is as given by resource grant
prb_dist->n_prb[0] = n_prb_1;
grant->n_prb[0] = n_prb_1;
if (n_prb_1 < n_rb_ho/2) {
fprintf(stderr, "Invalid Frequency Hopping parameters. Offset: %d, n_prb_1: %d\n", n_rb_ho, n_prb_1);
}
uint32_t n_prb_1_tilde = n_prb_1;
// prb idx for slot 1
switch(ra->freq_hop_fl) {
switch(dci->freq_hop_fl) {
case SRSLTE_RA_PUSCH_HOP_QUART:
prb_dist->n_prb[1] = (n_rb_pusch/4+ n_prb_1_tilde)%n_rb_pusch;
grant->n_prb[1] = (n_rb_pusch/4+ n_prb_1_tilde)%n_rb_pusch;
break;
case SRSLTE_RA_PUSCH_HOP_QUART_NEG:
if (n_prb_1 < n_rb_pusch/4) {
prb_dist->n_prb[1] = (n_rb_pusch+ n_prb_1_tilde -n_rb_pusch/4);
grant->n_prb[1] = (n_rb_pusch+ n_prb_1_tilde -n_rb_pusch/4);
} else {
prb_dist->n_prb[1] = (n_prb_1_tilde -n_rb_pusch/4);
grant->n_prb[1] = (n_prb_1_tilde -n_rb_pusch/4);
}
break;
case SRSLTE_RA_PUSCH_HOP_HALF:
prb_dist->n_prb[1] = (n_rb_pusch/2+ n_prb_1_tilde)%n_rb_pusch;
grant->n_prb[1] = (n_rb_pusch/2+ n_prb_1_tilde)%n_rb_pusch;
break;
default:
break;
}
INFO("n_rb_pusch: %d, prb1: %d, prb2: %d, L: %d\n", n_rb_pusch, prb_dist->n_prb[0], prb_dist->n_prb[1], prb_dist->L_prb);
prb_dist->freq_hopping = 1;
INFO("n_rb_pusch: %d, prb1: %d, prb2: %d, L: %d\n", n_rb_pusch, grant->n_prb[0], grant->n_prb[1], grant->L_prb);
grant->freq_hopping = 1;
}
return SRSLTE_SUCCESS;
}
static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant) {
// 8.6.2 First paragraph
if (dci->mcs_idx <= 28) {
/* Table 8.6.1-1 on 36.213 */
if (dci->mcs_idx < 11) {
grant->mcs.mod = SRSLTE_MOD_QPSK;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb);
} else if (dci->mcs_idx < 21) {
grant->mcs.mod = SRSLTE_MOD_16QAM;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx - 1, grant->L_prb);
} else if (dci->mcs_idx < 29) {
grant->mcs.mod = SRSLTE_MOD_64QAM;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx - 2, grant->L_prb);
} else {
fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx);
return SRSLTE_ERROR;
}
} else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) {
// 8.6.1 and 8.6.2 36.213 second paragraph
grant->mcs.mod = SRSLTE_MOD_QPSK;
grant->mcs.tbs = 0;
} else if (dci->mcs_idx >= 29) {
// Else use last TBS/Modulation and use mcs to obtain rv_idx
grant->mcs.tbs = 0;
grant->mcs.mod = 0;
dci->rv_idx = dci->mcs_idx - 28;
}
return SRSLTE_SUCCESS;
}
/** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */
int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, srslte_cell_t cell,
uint32_t n_rb_ho, uint32_t N_srs)
{
// Compute PRB allocation
if (!srslte_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, cell.nof_prb)) {
// Compute MCS
if (!ul_dci_to_grant_mcs(dci, grant)) {
// Fill rest of grant structure
grant->lstart = 0;
grant->nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs;
grant->M_sc = grant->L_prb*SRSLTE_NRE;
grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be?
grant->nof_re = grant->nof_symb*grant->M_sc;
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
grant->nof_bits = grant->nof_re * grant->Qm;
} else {
fprintf(stderr, "Error computing MCS\n");
return SRSLTE_ERROR;
}
} else {
fprintf(stderr, "Error computing PRB allocation\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
/* Computes the number of RE for each PRB in the prb_dist structure */
void srslte_ra_dl_alloc_re(srslte_ra_dl_alloc_t *prb_dist, uint32_t nof_prb, uint32_t nof_ports,
uint32_t nof_ctrl_symbols, srslte_cp_t cp) {
uint32_t i, j, s;
/* Set start symbol according to Section 7.1.6.4 in 36.213 */
prb_dist->lstart = nof_ctrl_symbols;
// Compute number of RE per subframe
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
prb_dist->re_sf[i] = 0;
for (s = 0; s < 2; s++) {
for (j = 0; j < nof_prb; j++) {
if (prb_dist->slot[s].prb_idx[j]) {
prb_dist->re_sf[i] += ra_re_x_prb(i, s, j,
nof_prb, nof_ports, nof_ctrl_symbols, cp);
}
void srslte_dl_dci_to_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell,
uint32_t sf_idx, uint32_t nof_ctrl_symbols)
{
uint32_t j, s;
// Compute number of RE per PRB
grant->nof_re = 0;
for (s = 0; s < 2; s++) {
for (j = 0; j < cell.nof_prb; j++) {
if (grant->prb_idx[s][j]) {
grant->nof_re += ra_re_x_prb(sf_idx, s, j,
cell.nof_prb, cell.nof_ports, nof_ctrl_symbols, cell.cp);
}
}
}
}
}
/** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */
int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, uint32_t nof_prb) {
static int dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, uint32_t nof_prb) {
int i, j;
uint32_t bitmask;
uint32_t P = srslte_ra_type0_P(nof_prb);
uint32_t n_rb_rbg_subset, n_rb_type1;
bzero(prb_dist, sizeof(srslte_ra_dl_alloc_t));
switch (ra->alloc_type) {
bzero(grant, sizeof(srslte_ra_dl_grant_t));
switch (dci->alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
bitmask = ra->type0_alloc.rbg_bitmask;
bitmask = dci->type0_alloc.rbg_bitmask;
int nb = (int) ceilf((float) nof_prb / P);
for (i = 0; i < nb; i++) {
if (bitmask & (1 << (nb - i - 1))) {
for (j = 0; j < P; j++) {
if (i*P+j < nof_prb) {
prb_dist->slot[0].prb_idx[i * P + j] = true;
prb_dist->slot[0].nof_prb++;
grant->prb_idx[0][i * P + j] = true;
grant->nof_prb++;
}
}
}
}
memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(srslte_ra_prb_slot_t));
memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool));
break;
case SRSLTE_RA_ALLOC_TYPE1:
n_rb_type1 = srslte_ra_type1_N_rb(nof_prb);
if (ra->type1_alloc.rbg_subset < (nof_prb / P) % P) {
if (dci->type1_alloc.rbg_subset < (nof_prb / P) % P) {
n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P + P;
} else if (ra->type1_alloc.rbg_subset == ((nof_prb / P) % P)) {
} else if (dci->type1_alloc.rbg_subset == ((nof_prb / P) % P)) {
n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P + ((nof_prb - 1) % P) + 1;
} else {
n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P;
}
int shift = ra->type1_alloc.shift ? (n_rb_rbg_subset - n_rb_type1) : 0;
bitmask = ra->type1_alloc.vrb_bitmask;
int shift = dci->type1_alloc.shift ? (n_rb_rbg_subset - n_rb_type1) : 0;
bitmask = dci->type1_alloc.vrb_bitmask;
for (i = 0; i < n_rb_type1; i++) {
if (bitmask & (1 << (n_rb_type1 - i - 1))) {
prb_dist->slot[0].prb_idx[((i + shift) / P)
* P * P + ra->type1_alloc.rbg_subset * P + (i + shift) % P] = true;
prb_dist->slot[0].nof_prb++;
grant->prb_idx[0][((i + shift) / P)
* P * P + dci->type1_alloc.rbg_subset * P + (i + shift) % P] = true;
grant->nof_prb++;
}
}
memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(srslte_ra_prb_slot_t));
memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool));
break;
case SRSLTE_RA_ALLOC_TYPE2:
if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
for (i = 0; i < ra->type2_alloc.L_crb; i++) {
prb_dist->slot[0].prb_idx[i + ra->type2_alloc.RB_start] = true;
prb_dist->slot[0].nof_prb++;
if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
for (i = 0; i < dci->type2_alloc.L_crb; i++) {
grant->prb_idx[0][i + dci->type2_alloc.RB_start] = true;
grant->nof_prb++;
}
memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(srslte_ra_prb_slot_t));
memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool));
} else {
/* Mapping of Virtual to Physical RB for distributed type is defined in
* 6.2.3.2 of 36.211
@ -262,7 +306,7 @@ int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, ui
int N_gap, N_tilde_vrb, n_tilde_vrb, n_tilde_prb, n_tilde2_prb, N_null,
N_row, n_vrb;
int n_tilde_prb_odd, n_tilde_prb_even;
if (ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1) {
if (dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1) {
N_tilde_vrb = srslte_ra_type2_n_vrb_dl(nof_prb, true);
N_gap = srslte_ra_type2_ngap(nof_prb, true);
} else {
@ -271,8 +315,8 @@ int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, ui
}
N_row = (int) ceilf((float) N_tilde_vrb / (4 * P)) * P;
N_null = 4 * N_row - N_tilde_vrb;
for (i = 0; i < ra->type2_alloc.L_crb; i++) {
n_vrb = i + ra->type2_alloc.RB_start;
for (i = 0; i < dci->type2_alloc.L_crb; i++) {
n_vrb = i + dci->type2_alloc.RB_start;
n_tilde_vrb = n_vrb % N_tilde_vrb;
n_tilde_prb = 2 * N_row * (n_tilde_vrb % 2) + n_tilde_vrb / 2
+ N_tilde_vrb * (n_vrb / N_tilde_vrb);
@ -295,19 +339,18 @@ int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, ui
+ N_tilde_vrb * (n_vrb / N_tilde_vrb);
if (n_tilde_prb_odd < N_tilde_vrb / 2) {
prb_dist->slot[0].prb_idx[n_tilde_prb_odd] = true;
grant->prb_idx[0][n_tilde_prb_odd] = true;
} else {
prb_dist->slot[0].prb_idx[n_tilde_prb_odd + N_gap
grant->prb_idx[0][n_tilde_prb_odd + N_gap
- N_tilde_vrb / 2] = true;
}
prb_dist->slot[0].nof_prb++;
grant->nof_prb++;
if (n_tilde_prb_even < N_tilde_vrb / 2) {
prb_dist->slot[1].prb_idx[n_tilde_prb_even] = true;
grant->prb_idx[1][n_tilde_prb_even] = true;
} else {
prb_dist->slot[1].prb_idx[n_tilde_prb_even + N_gap
grant->prb_idx[1][n_tilde_prb_even + N_gap
- N_tilde_vrb / 2] = true;
}
prb_dist->slot[1].nof_prb++;
}
}
break;
@ -318,46 +361,83 @@ int srslte_ra_dl_alloc(srslte_ra_dl_alloc_t *prb_dist, srslte_ra_pdsch_t *ra, ui
return SRSLTE_SUCCESS;
}
/* Returns the number of allocated PRB for Uplink */
uint32_t srslte_ra_nprb_ul(srslte_ra_pusch_t *ra, uint32_t nof_prb) {
return ra->type2_alloc.L_crb;
/* Modulation order and transport block size determination 7.1.7 in 36.213 */
static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, bool crc_is_crnti) {
uint32_t n_prb;
switch(dci->dci_format) {
case SRSLTE_RA_DCI_FORMAT1:
/* Table 7.1.7.1-1 on 36.213 */
if (dci->mcs_idx < 10) {
grant->mcs.mod = SRSLTE_MOD_QPSK;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->nof_prb);
} else if (dci->mcs_idx < 17) {
grant->mcs.mod = !crc_is_crnti?SRSLTE_MOD_QPSK:SRSLTE_MOD_16QAM;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx - 1, grant->nof_prb);
} else if (dci->mcs_idx < 29) {
grant->mcs.mod = !crc_is_crnti?SRSLTE_MOD_QPSK:SRSLTE_MOD_64QAM;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx - 2, grant->nof_prb);
} else if (dci->mcs_idx == 29) {
grant->mcs.mod = SRSLTE_MOD_QPSK;
grant->mcs.tbs = 0;
} else if (dci->mcs_idx == 30) {
grant->mcs.mod = !crc_is_crnti?SRSLTE_MOD_QPSK:SRSLTE_MOD_16QAM;
grant->mcs.tbs = 0;
} else if (dci->mcs_idx == 31) {
grant->mcs.mod = !crc_is_crnti?SRSLTE_MOD_QPSK:SRSLTE_MOD_64QAM;
grant->mcs.tbs = 0;
} else {
return SRSLTE_ERROR;
}
break;
case SRSLTE_RA_DCI_FORMAT1A:
/* Downlink Transport Block size determination as defined in 7.1.7.2 on 36.213 */
if (crc_is_crnti) {
n_prb = grant->nof_prb;
} else {
n_prb = dci->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3;
}
if (dci->mcs_idx < 27 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) {
grant->mcs.tbs = tbs_table[dci->mcs_idx][n_prb - 1];
grant->mcs.mod = SRSLTE_MOD_QPSK;
} else {
return SRSLTE_ERROR;
}
break;
case SRSLTE_RA_DCI_FORMAT1C:
/* Downlink Transport Block size for Format 1C as defined in 7.1.7.2.2-1 on 36.213 */
if (dci->mcs_idx < 32) {
grant->mcs.tbs = tbs_format1c_table[dci->mcs_idx];
grant->mcs.mod = SRSLTE_MOD_QPSK;
} else {
return SRSLTE_ERROR;
}
break;
}
return SRSLTE_SUCCESS;
}
/* Returns the number of allocated PRB for Downlink */
uint32_t srslte_ra_nprb_dl(srslte_ra_pdsch_t *ra, uint32_t nof_prb) {
uint32_t nprb;
uint32_t nof_rbg, P;
switch (ra->alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
// Get the number of allocated RBG except the last RBG
nof_rbg = srslte_bit_count(ra->type0_alloc.rbg_bitmask & 0xFFFFFFFE);
P = srslte_ra_type0_P(nof_prb);
if (nof_rbg > (uint32_t) ceilf((float) nof_prb / P)) {
nof_rbg = (uint32_t) ceilf((float) nof_prb / P) - 1;
}
nprb = nof_rbg * P;
// last RBG may have smaller size. Add if set
uint32_t P_last = (nof_prb % P);
if (!P_last)
P_last = P;
nprb += P_last * (ra->type0_alloc.rbg_bitmask & 1);
break;
case SRSLTE_RA_ALLOC_TYPE1:
nprb = srslte_bit_count(ra->type1_alloc.vrb_bitmask);
if (nprb > srslte_ra_type1_N_rb(nof_prb)) {
fprintf(stderr, "Number of RB (%d) can not exceed %d\n", nprb,
srslte_ra_type1_N_rb(nof_prb));
return SRSLTE_ERROR;
/** Obtains a DL grant from a DCI grant for PDSCH */
int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, srslte_cell_t cell,
uint32_t sf_idx, uint32_t cfi, bool crc_is_crnti)
{
// Compute PRB allocation
if (!dl_dci_to_grant_prb_allocation(dci, grant, cell.nof_prb)) {
// Compute number of RE
srslte_dl_dci_to_grant_nof_re(grant, cell, sf_idx, cell.nof_prb<10?(cfi+1):cfi);
// Compute MCS
if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) {
// Fill rest of grant structure
grant->lstart = cell.nof_prb<10?(cfi+1):cfi;
grant->nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-grant->lstart;
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
grant->nof_bits = grant->nof_re * grant->Qm;
} else {
return SRSLTE_ERROR;
}
break;
case SRSLTE_RA_ALLOC_TYPE2:
nprb = ra->type2_alloc.L_crb;
break;
default:
return SRSLTE_ERROR;
} else {
return SRSLTE_ERROR;
}
return nprb;
return SRSLTE_SUCCESS;
}
/* RBG size for type0 scheduling as in table 7.1.6.1-1 of 36.213 */
@ -443,59 +523,7 @@ uint32_t srslte_ra_type2_n_vrb_dl(uint32_t nof_prb, bool ngap_is_1) {
}
}
/* Converts MCS index to srslte_ra_mcs_t structure for Downlink as defined inTable 7.1.7.1-1 on 36.213 */
int srslte_ra_mcs_from_idx_dl(uint32_t mcs_idx, uint32_t nof_prb, srslte_ra_mcs_t *mcs) {
if (mcs_idx < 10) {
mcs->mod = SRSLTE_MOD_QPSK;
mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx, nof_prb);
} else if (mcs_idx < 17) {
mcs->mod = SRSLTE_MOD_16QAM;
mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx - 1, nof_prb);
} else if (mcs_idx < 29) {
mcs->mod = SRSLTE_MOD_64QAM;
mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx - 2, nof_prb);
} else if (mcs_idx == 29) {
mcs->mod = SRSLTE_MOD_QPSK;
mcs->tbs = 0;
} else if (mcs_idx == 30) {
mcs->mod = SRSLTE_MOD_16QAM;
mcs->tbs = 0;
} else if (mcs_idx == 31) {
mcs->mod = SRSLTE_MOD_64QAM;
mcs->tbs = 0;
} else {
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
/* Converts MCS index to srslte_ra_mcs_t structure for Uplink as defined in Table 8.6.1-1 on 36.213 */
int srslte_ra_mcs_from_idx_ul(uint32_t mcs_idx, uint32_t nof_prb, srslte_ra_mcs_t *mcs) {
if (mcs_idx < 11) {
mcs->mod = SRSLTE_MOD_QPSK;
mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx, nof_prb);
} else if (mcs_idx < 21) {
mcs->mod = SRSLTE_MOD_16QAM;
mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx - 1, nof_prb);
} else if (mcs_idx < 29) {
mcs->mod = SRSLTE_MOD_64QAM;
mcs->tbs = srslte_ra_tbs_from_idx(mcs_idx - 2, nof_prb);
} else {
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
/* Downlink Transport Block size for Format 1C as defined in 7.1.7.2.2-1 on 36.213 */
int srslte_ra_tbs_from_idx_format1c(uint32_t tbs_idx) {
if (tbs_idx < 32) {
return tbs_format1c_table[tbs_idx];
} else {
return SRSLTE_ERROR;
}
}
/* Downlink Transport Block size determination as defined in 7.1.7.2 on 36.213 */
/* Table 7.1.7.2.1-1: Transport block size table on 36.213 */
int srslte_ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb) {
if (tbs_idx < 27 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) {
return tbs_table[tbs_idx][n_prb - 1];
@ -523,39 +551,42 @@ int srslte_ra_tbs_to_table_idx(uint32_t tbs, uint32_t n_prb) {
return SRSLTE_ERROR;
}
void srslte_ra_pusch_fprint(FILE *f, srslte_ra_pusch_t *ra, uint32_t nof_prb) {
void srslte_ra_pusch_fprint(FILE *f, srslte_ra_ul_dci_t *dci, uint32_t nof_prb) {
fprintf(f, " - Resource Allocation Type 2 mode :\t%s\n",
ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC ? "Localized" : "Distributed");
dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC ? "Localized" : "Distributed");
fprintf(f, " + Frequency Hopping:\t\t\t");
if (ra->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) {
if (dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) {
fprintf(f, "No\n");
} else {
fprintf(f, "Yes\n");
}
fprintf(f, " + Resource Indicator Value:\t\t%d\n", ra->type2_alloc.riv);
if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
fprintf(f, " + Resource Indicator Value:\t\t%d\n", dci->type2_alloc.riv);
if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n",
ra->type2_alloc.L_crb, ra->type2_alloc.RB_start);
dci->type2_alloc.L_crb, dci->type2_alloc.RB_start);
} else {
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n",
ra->type2_alloc.L_crb, ra->type2_alloc.RB_start);
dci->type2_alloc.L_crb, dci->type2_alloc.RB_start);
fprintf(f, " + VRB gap selection:\t\t\tGap %d\n",
ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1 ? 1 : 2);
dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1 ? 1 : 2);
fprintf(f, " + VRB gap:\t\t\t\t%d\n",
srslte_ra_type2_ngap(nof_prb, ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1));
srslte_ra_type2_ngap(nof_prb, dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1));
}
fprintf(f, " - Number of PRBs:\t\t\t%d\n", srslte_ra_nprb_ul(ra, nof_prb));
fprintf(f, " - Modulation and coding scheme index:\t%d\n", ra->mcs_idx);
fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(ra->mcs.mod));
fprintf(f, " - Transport block size:\t\t%d\n", ra->mcs.tbs);
fprintf(f, " - New data indicator:\t\t\t%s\n", ra->ndi ? "Yes" : "No");
fprintf(f, " - Redundancy version:\t\t\t%d\n", ra->rv_idx);
fprintf(f, " - Modulation and coding scheme index:\t%d\n", dci->mcs_idx);
fprintf(f, " - New data indicator:\t\t\t%s\n", dci->ndi ? "Yes" : "No");
fprintf(f, " - Redundancy version:\t\t\t%d\n", dci->rv_idx);
fprintf(f, " - TPC command for PUCCH:\t\t--\n");
}
void srslte_ra_ul_grant_fprint(FILE *f, srslte_ra_ul_grant_t *grant) {
fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->L_prb);
fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs.mod));
fprintf(f, " - Transport block size:\t\t%d\n", grant->mcs.tbs);
}
char *ra_type_string(srslte_ra_type_t alloc_type) {
switch (alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
@ -569,54 +600,65 @@ char *ra_type_string(srslte_ra_type_t alloc_type) {
}
}
void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_pdsch_t *ra, uint32_t nof_prb) {
void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_dl_dci_t *dci, uint32_t nof_prb) {
fprintf(f, " - Resource Allocation Type:\t\t%s\n",
ra_type_string(ra->alloc_type));
switch (ra->alloc_type) {
ra_type_string(dci->alloc_type));
switch (dci->alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
fprintf(f, " + Resource Block Group Size:\t\t%d\n", srslte_ra_type0_P(nof_prb));
fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n", ra->type0_alloc.rbg_bitmask);
fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n", dci->type0_alloc.rbg_bitmask);
break;
case SRSLTE_RA_ALLOC_TYPE1:
fprintf(f, " + Resource Block Group Size:\t\t%d\n", srslte_ra_type0_P(nof_prb));
fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n", ra->type1_alloc.vrb_bitmask);
fprintf(f, " + RBG Subset:\t\t\t%d\n", ra->type1_alloc.rbg_subset);
fprintf(f, " + RBG Bitmap:\t\t\t0x%x\n", dci->type1_alloc.vrb_bitmask);
fprintf(f, " + RBG Subset:\t\t\t%d\n", dci->type1_alloc.rbg_subset);
fprintf(f, " + RBG Shift:\t\t\t\t%s\n",
ra->type1_alloc.shift ? "Yes" : "No");
dci->type1_alloc.shift ? "Yes" : "No");
break;
case SRSLTE_RA_ALLOC_TYPE2:
fprintf(f, " + Type:\t\t\t\t%s\n",
ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC ? "Localized" : "Distributed");
fprintf(f, " + Resource Indicator Value:\t\t%d\n", ra->type2_alloc.riv);
if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC ? "Localized" : "Distributed");
fprintf(f, " + Resource Indicator Value:\t\t%d\n", dci->type2_alloc.riv);
if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n",
ra->type2_alloc.L_crb, ra->type2_alloc.RB_start);
dci->type2_alloc.L_crb, dci->type2_alloc.RB_start);
} else {
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n",
ra->type2_alloc.L_crb, ra->type2_alloc.RB_start);
dci->type2_alloc.L_crb, dci->type2_alloc.RB_start);
fprintf(f, " + VRB gap selection:\t\t\tGap %d\n",
ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1 ? 1 : 2);
dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1 ? 1 : 2);
fprintf(f, " + VRB gap:\t\t\t\t%d\n",
srslte_ra_type2_ngap(nof_prb, ra->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1));
srslte_ra_type2_ngap(nof_prb, dci->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1));
}
break;
}
fprintf(f, " - Modulation and coding scheme index:\t%d\n", dci->mcs_idx);
fprintf(f, " - HARQ process:\t\t\t%d\n", dci->harq_process);
fprintf(f, " - New data indicator:\t\t\t%s\n", dci->ndi ? "Yes" : "No");
fprintf(f, " - Redundancy version:\t\t\t%d\n", dci->rv_idx);
fprintf(f, " - TPC command for PUCCH:\t\t--\n");
}
srslte_ra_dl_alloc_t alloc;
srslte_ra_dl_alloc(&alloc, ra, nof_prb);
for (int s = 0; s < 2; s++) {
fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", s);
srslte_ra_prb_fprint(f, &alloc.slot[s], nof_prb);
}
void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
srslte_ra_prb_fprint(f, grant);
fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb);
fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs.mod));
fprintf(f, " - Transport block size:\t\t%d\n", grant->mcs.tbs);
}
fprintf(f, " - Number of PRBs:\t\t\t%d\n", srslte_ra_nprb_dl(ra, nof_prb));
fprintf(f, " - Modulation and coding scheme index:\t%d\n", ra->mcs_idx);
fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(ra->mcs.mod));
fprintf(f, " - Transport block size:\t\t%d\n", ra->mcs.tbs);
fprintf(f, " - HARQ process:\t\t\t%d\n", ra->harq_process);
fprintf(f, " - New data indicator:\t\t\t%s\n", ra->ndi ? "Yes" : "No");
fprintf(f, " - Redundancy version:\t\t\t%d\n", ra->rv_idx);
fprintf(f, " - TPC command for PUCCH:\t\t--\n");
void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
if (grant->nof_prb > 0) {
for (int j=0;j<2;j++) {
fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", j);
for (int i=0;i<SRSLTE_MAX_PRB;i++) {
if (grant->prb_idx[j][i]) {
fprintf(f, "%d, ", i);
}
}
fprintf(f, "\n");
}
}
}

@ -34,6 +34,7 @@
#include <assert.h>
#include <math.h>
#include "srslte/phch/pdsch.h"
#include "srslte/phch/pusch.h"
#include "srslte/phch/sch.h"
#include "srslte/phch/uci.h"
@ -55,6 +56,33 @@ float beta_cqi_offset[16] = {-1.0, -1.0, 1.125, 1.25, 1.375, 1.625, 1.750, 2.0,
3.125, 3.5, 4.0, 5.0, 6.25};
uint32_t srslte_sch_find_Ioffset_ack(float beta) {
for (int i=0;i<16;i++) {
if (beta_harq_offset[i] >= beta) {
return i;
}
}
return 0;
}
uint32_t srslte_sch_find_Ioffset_ri(float beta) {
for (int i=0;i<16;i++) {
if (beta_ri_offset[i] >= beta) {
return i;
}
}
return 0;
}
uint32_t srslte_sch_find_Ioffset_cqi(float beta) {
for (int i=0;i<16;i++) {
if (beta_cqi_offset[i] >= beta) {
return i;
}
}
return 0;
}
int srslte_sch_init(srslte_sch_t *q) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q) {
@ -69,22 +97,22 @@ int srslte_sch_init(srslte_sch_t *q) {
goto clean;
}
if (srslte_tcod_init(&q->encoder, MAX_LONG_CB)) {
if (srslte_tcod_init(&q->encoder, SRSLTE_TCOD_MAX_LEN_CB)) {
fprintf(stderr, "Error initiating Turbo Coder\n");
goto clean;
}
if (srslte_tdec_init(&q->decoder, MAX_LONG_CB)) {
if (srslte_tdec_init(&q->decoder, SRSLTE_TCOD_MAX_LEN_CB)) {
fprintf(stderr, "Error initiating Turbo Decoder\n");
goto clean;
}
// Allocate floats for reception (LLRs)
q->cb_in = srslte_vec_malloc(sizeof(uint8_t) * MAX_LONG_CB);
q->cb_in = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_TCOD_MAX_LEN_CB);
if (!q->cb_in) {
goto clean;
}
q->cb_out = srslte_vec_malloc(sizeof(float) * (3 * MAX_LONG_CB + 12));
q->cb_out = srslte_vec_malloc(sizeof(float) * (3 * SRSLTE_TCOD_MAX_LEN_CB + 12));
if (!q->cb_out) {
goto clean;
}
@ -128,7 +156,10 @@ uint32_t srslte_sch_last_noi(srslte_sch_t *q) {
/* Encode a transport block according to 36.212 5.3.2
*
*/
static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_t *e_bits, uint32_t nof_e_bits)
static int encode_tb(srslte_sch_t *q,
srslte_softbuffer_tx_t *soft_buffer, srslte_cbsegm_t *cb_segm,
uint32_t Qm, uint32_t rv, uint32_t nof_e_bits,
uint8_t *data, uint8_t *e_bits)
{
uint8_t parity[24];
uint8_t *p_parity = parity;
@ -136,30 +167,31 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_
uint32_t i;
uint32_t cb_len, rp, wp, rlen, F, n_e;
int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t Qm = srslte_mod_bits_x_symbol(harq->mcs.mod);
if (q != NULL &&
data != NULL &&
harq != NULL)
if (q != NULL &&
data != NULL &&
e_bits != NULL &&
cb_segm != NULL &&
soft_buffer != NULL)
{
uint32_t Gp = nof_e_bits / Qm;
uint32_t gamma = Gp;
if (harq->cb_segm.C > 0) {
gamma = Gp%harq->cb_segm.C;
if (cb_segm->C > 0) {
gamma = Gp%cb_segm->C;
}
if (harq->rv == 0) {
if (rv == 0) {
/* Compute transport block CRC */
par = srslte_crc_checksum(&q->crc_tb, data, harq->mcs.tbs);
par = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs);
/* parity bits will be appended later */
srslte_bit_pack(par, &p_parity, 24);
if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("DATA: ", 0);
srslte_vec_fprint_b(stdout, data, harq->mcs.tbs);
srslte_vec_fprint_b(stdout, data, cb_segm->tbs);
DEBUG("PARITY: ", 0);
srslte_vec_fprint_b(stdout, parity, 24);
}
@ -167,37 +199,37 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_
wp = 0;
rp = 0;
for (i = 0; i < harq->cb_segm.C; i++) {
for (i = 0; i < cb_segm->C; i++) {
/* Get read lengths */
if (i < harq->cb_segm.C2) {
cb_len = harq->cb_segm.K2;
if (i < cb_segm->C2) {
cb_len = cb_segm->K2;
} else {
cb_len = harq->cb_segm.K1;
cb_len = cb_segm->K1;
}
if (harq->cb_segm.C > 1) {
if (cb_segm->C > 1) {
rlen = cb_len - 24;
} else {
rlen = cb_len;
}
if (i == 0) {
F = harq->cb_segm.F;
F = cb_segm->F;
} else {
F = 0;
}
if (i <= harq->cb_segm.C - gamma - 1) {
n_e = Qm * (Gp/harq->cb_segm.C);
if (i <= cb_segm->C - gamma - 1) {
n_e = Qm * (Gp/cb_segm->C);
} else {
n_e = Qm * ((uint32_t) ceilf((float) Gp/harq->cb_segm.C));
n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C));
}
INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i,
cb_len, rlen - F, wp, rp, F, n_e);
if (harq->rv == 0) {
if (rv == 0) {
/* Copy data to another buffer, making space for the Codeblock CRC */
if (i < harq->cb_segm.C - 1) {
if (i < cb_segm->C - 1) {
// Copy data
memcpy(&q->cb_in[F], &data[rp], (rlen - F) * sizeof(uint8_t));
} else {
@ -212,7 +244,7 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_
q->cb_in[j] = 0;
}
/* Attach Codeblock CRC */
if (harq->cb_segm.C > 1) {
if (cb_segm->C > 1) {
srslte_crc_attach(&q->crc_cb, q->cb_in, rlen);
}
/* Set the filler bits to <NULL> */
@ -229,9 +261,9 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_
}
/* Rate matching */
if (srslte_rm_turbo_tx(harq->pdsch_w_buff_c[i], harq->w_buff_size,
if (srslte_rm_turbo_tx(soft_buffer->buffer_b[i], soft_buffer->buff_size,
(uint8_t*) q->cb_out, 3 * cb_len + 12,
&e_bits[wp], n_e, harq->rv))
&e_bits[wp], n_e, rv))
{
fprintf(stderr, "Error in rate matching\n");
return SRSLTE_ERROR;
@ -251,21 +283,25 @@ static int encode_tb(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_
/* Decode a transport block according to 36.212 5.3.2
*
*/
static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_t *data, uint32_t nof_e_bits)
static int decode_tb(srslte_sch_t *q,
srslte_softbuffer_rx_t *softbuffer, srslte_cbsegm_t *cb_segm,
uint32_t Qm, uint32_t rv, uint32_t nof_e_bits,
float *e_bits, uint8_t *data)
{
uint8_t parity[24];
uint8_t *p_parity = parity;
uint32_t par_rx, par_tx;
uint32_t i;
uint32_t cb_len, rp, wp, rlen, F, n_e;
uint32_t Qm = srslte_mod_bits_x_symbol(harq->mcs.mod);
if (q != NULL &&
data != NULL &&
harq != NULL)
if (q != NULL &&
data != NULL &&
softbuffer != NULL &&
e_bits != NULL &&
cb_segm != NULL)
{
if (harq->mcs.tbs == 0 || harq->cb_segm.C == 0) {
if (cb_segm->tbs == 0 || cb_segm->C == 0) {
return SRSLTE_SUCCESS;
}
@ -275,43 +311,43 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_
uint32_t Gp = nof_e_bits / Qm;
uint32_t gamma=Gp;
if (harq->cb_segm.C>0) {
gamma = Gp%harq->cb_segm.C;
if (cb_segm->C>0) {
gamma = Gp%cb_segm->C;
}
bool early_stop = true;
for (i = 0; i < harq->cb_segm.C && early_stop; i++) {
for (i = 0; i < cb_segm->C && early_stop; i++) {
/* Get read/write lengths */
if (i < harq->cb_segm.C2) {
cb_len = harq->cb_segm.K2;
if (i < cb_segm->C2) {
cb_len = cb_segm->K2;
} else {
cb_len = harq->cb_segm.K1;
cb_len = cb_segm->K1;
}
if (harq->cb_segm.C == 1) {
if (cb_segm->C == 1) {
rlen = cb_len;
} else {
rlen = cb_len - 24;
}
if (i == 0) {
F = harq->cb_segm.F;
F = cb_segm->F;
} else {
F = 0;
}
if (i <= harq->cb_segm.C - gamma - 1) {
n_e = Qm * (Gp/harq->cb_segm.C);
if (i <= cb_segm->C - gamma - 1) {
n_e = Qm * (Gp/cb_segm->C);
} else {
n_e = Qm * ((uint32_t) ceilf((float) Gp/harq->cb_segm.C));
n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C));
}
INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i,
cb_len, rlen - F, wp, rp, F, n_e);
/* Rate Unmatching */
if (srslte_rm_turbo_rx(harq->pdsch_w_buff_f[i], harq->w_buff_size,
if (srslte_rm_turbo_rx(softbuffer->buffer_f[i], softbuffer->buff_size,
&e_bits[rp], n_e,
(float*) q->cb_out, 3 * cb_len + 12, harq->rv, F)) {
(float*) q->cb_out, 3 * cb_len + 12, rv, F)) {
fprintf(stderr, "Error in rate matching\n");
return SRSLTE_ERROR;
}
@ -334,12 +370,12 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_
srslte_tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len);
q->nof_iterations++;
if (harq->cb_segm.C > 1) {
if (cb_segm->C > 1) {
len_crc = cb_len;
cb_in_ptr = q->cb_in;
crc_ptr = &q->crc_cb;
} else {
len_crc = harq->mcs.tbs+24;
len_crc = cb_segm->tbs+24;
cb_in_ptr = &q->cb_in[F];
crc_ptr = &q->crc_tb;
}
@ -362,7 +398,7 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_
// If CB CRC is not correct, early_stop will be false and wont continue with rest of CBs
/* Copy data to another buffer, removing the Codeblock CRC */
if (i < harq->cb_segm.C - 1) {
if (i < cb_segm->C - 1) {
memcpy(&data[wp], &q->cb_in[F], (rlen - F) * sizeof(uint8_t));
} else {
DEBUG("Last CB, appending parity: %d to %d from %d and 24 from %d\n",
@ -385,7 +421,7 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_
INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp);
// Compute transport block CRC
par_rx = srslte_crc_checksum(&q->crc_tb, data, harq->mcs.tbs);
par_rx = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs);
// check parity bits
par_tx = srslte_bit_unpack(&p_parity, 24);
@ -408,23 +444,36 @@ static int decode_tb(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_
}
}
int srslte_dlsch_decode(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_t *data)
int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
float *e_bits, uint8_t *data)
{
return decode_tb(q, harq, e_bits, data, harq->nof_bits);
return decode_tb(q,
softbuffer, &cfg->cb_segm,
cfg->grant.Qm, cfg->rv, cfg->grant.nof_bits,
e_bits, data);
}
int srslte_dlsch_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_t *e_bits) {
return encode_tb(q, harq, data, e_bits, harq->nof_bits);
int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, uint8_t *e_bits)
{
return encode_tb(q,
softbuffer, &cfg->cb_segm,
cfg->grant.Qm, cfg->rv, cfg->grant.nof_bits,
data, e_bits);
}
int srslte_ulsch_decode(srslte_sch_t *q, srslte_harq_t *harq, float *e_bits, uint8_t *data)
int srslte_ulsch_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
float *e_bits, uint8_t *data)
{
return decode_tb(q, harq, e_bits, data, harq->nof_bits);
return decode_tb(q,
softbuffer, &cfg->cb_segm,
cfg->grant.Qm, cfg->rv, cfg->grant.nof_bits,
e_bits, data);
}
/* UL-SCH channel interleaver according to 5.5.2.8 of 36.212 */
void ulsch_interleave(uint8_t *g_bits, uint32_t Q_m, uint32_t H_prime_total, uint32_t N_pusch_symbs, uint8_t *q_bits)
void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, uint8_t *q_bits)
{
uint32_t rows = H_prime_total/N_pusch_symbs;
@ -433,11 +482,11 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Q_m, uint32_t H_prime_total, uin
uint32_t idx = 0;
for(uint32_t j=0; j<rows; j++) {
for(uint32_t i=0; i<cols; i++) {
for(uint32_t k=0; k<Q_m; k++) {
if (q_bits[j*Q_m + i*rows*Q_m + k] >= 10) {
q_bits[j*Q_m + i*rows*Q_m + k] -= 10;
for(uint32_t k=0; k<Qm; k++) {
if (q_bits[j*Qm + i*rows*Qm + k] >= 10) {
q_bits[j*Qm + i*rows*Qm + k] -= 10;
} else {
q_bits[j*Q_m + i*rows*Q_m + k] = g_bits[idx];
q_bits[j*Qm + i*rows*Qm + k] = g_bits[idx];
idx++;
}
}
@ -446,15 +495,18 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Q_m, uint32_t H_prime_total, uin
}
int srslte_ulsch_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, uint8_t *g_bits, uint8_t *q_bits)
int srslte_ulsch_encode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, uint8_t *g_bits, uint8_t *q_bits)
{
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return srslte_ulsch_uci_encode(q, harq, data, uci_data, g_bits, q_bits);
return srslte_ulsch_uci_encode(q, cfg, softbuffer, data, uci_data, g_bits, q_bits);
}
int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data, srslte_uci_data_t uci_data, uint8_t *g_bits, uint8_t *q_bits)
int srslte_ulsch_uci_encode(srslte_sch_t *q,
srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, srslte_uci_data_t uci_data,
uint8_t *g_bits, uint8_t *q_bits)
{
int ret;
@ -462,20 +514,19 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data,
uint32_t Q_prime_cqi = 0;
uint32_t Q_prime_ack = 0;
uint32_t Q_prime_ri = 0;
uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod);
uint32_t nof_symbols = 12*harq->ul_alloc.L_prb*SRSLTE_NRE;
uint32_t nb_q = nof_symbols * Q_m;
uint32_t nb_q = cfg->grant.nof_bits;
uint32_t Qm = cfg->grant.Qm;
bzero(q_bits, sizeof(uint8_t) * nb_q);
// Encode RI
if (uci_data.uci_ri_len > 0) {
float beta = beta_ri_offset[uci_data.I_offset_ri];
if (harq->mcs.tbs == 0) {
if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[uci_data.I_offset_cqi];
}
ret = srslte_uci_encode_ri(uci_data.uci_ri, uci_data.uci_cqi_len, beta, harq, nb_q/Q_m, q_bits);
ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits);
if (ret < 0) {
return ret;
}
@ -484,37 +535,39 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data,
// Encode CQI
if (uci_data.uci_cqi_len > 0) {
ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, uci_data.uci_cqi, uci_data.uci_cqi_len,
ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, cfg,
uci_data.uci_cqi, uci_data.uci_cqi_len,
beta_cqi_offset[uci_data.I_offset_cqi],
Q_prime_ri, harq, g_bits);
Q_prime_ri, g_bits);
if (ret < 0) {
return ret;
}
Q_prime_cqi = (uint32_t) ret;
}
e_offset += Q_prime_cqi*Q_m;
e_offset += Q_prime_cqi*Qm;
// Encode UL-SCH
if (harq->mcs.tbs > 0) {
uint32_t G = nb_q/Q_m - Q_prime_ri - Q_prime_cqi;
ret = encode_tb(q, harq, data, &g_bits[e_offset], G*Q_m);
if (cfg->cb_segm.tbs > 0) {
uint32_t G = nb_q/Qm - Q_prime_ri - Q_prime_cqi;
ret = encode_tb(q, softbuffer, &cfg->cb_segm,
Qm, cfg->rv, G*Qm,
data, &g_bits[e_offset]);
if (ret) {
return ret;
}
}
// Interleave UL-SCH (and RI and CQI)
ulsch_interleave(g_bits, Q_m, nb_q/Q_m, harq->nof_symb, q_bits);
ulsch_interleave(g_bits, Qm, nb_q/Qm, cfg->grant.nof_symb, q_bits);
// Encode (and interleave) ACK
if (uci_data.uci_ack_len > 0) {
float beta = beta_harq_offset[uci_data.I_offset_ack];
if (harq->mcs.tbs == 0) {
if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[uci_data.I_offset_cqi];
}
ret = srslte_uci_encode_ack(uci_data.uci_ack, uci_data.uci_cqi_len, beta, harq, nb_q/Q_m, q_bits);
ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits);
if (ret < 0) {
return ret;
}
@ -523,8 +576,6 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data,
INFO("Q_prime_ack=%d, Q_prime_cqi=%d, Q_prime_ri=%d\n",Q_prime_ack, Q_prime_cqi, Q_prime_ri);
return SRSLTE_SUCCESS;
}

@ -0,0 +1,164 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include "srslte/common/phy_common.h"
#include "srslte/phch/ra.h"
#include "srslte/fec/turbodecoder.h"
#include "srslte/phch/softbuffer.h"
#include "srslte/utils/vector.h"
#include "srslte/utils/debug.h"
#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, srslte_cell_t cell) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_softbuffer_rx_t));
ret = srslte_ra_tbs_from_idx(26, cell.nof_prb);
if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;
q->buffer_f = srslte_vec_malloc(sizeof(float*) * q->max_cb);
if (!q->buffer_f) {
perror("malloc");
return SRSLTE_ERROR;
}
// FIXME: Use HARQ buffer limitation based on UE category
q->buff_size = cell.nof_prb * MAX_PDSCH_RE(cell.cp) * 6 * 10;
for (uint32_t i=0;i<q->max_cb;i++) {
q->buffer_f[i] = srslte_vec_malloc(sizeof(float) * q->buff_size);
if (!q->buffer_f[i]) {
perror("malloc");
return SRSLTE_ERROR;
}
}
srslte_softbuffer_rx_reset(q);
ret = SRSLTE_SUCCESS;
}
}
return ret;
}
void srslte_softbuffer_rx_free(srslte_softbuffer_rx_t *q) {
if (q) {
if (q->buffer_f) {
for (uint32_t i=0;i<q->max_cb;i++) {
if (q->buffer_f[i]) {
free(q->buffer_f[i]);
}
}
free(q->buffer_f);
}
bzero(q, sizeof(srslte_softbuffer_rx_t));
}
}
void srslte_softbuffer_rx_reset(srslte_softbuffer_rx_t *q) {
int i;
if (q->buffer_f) {
for (i=0;i<q->max_cb;i++) {
if (q->buffer_f[i]) {
bzero(q->buffer_f[i], sizeof(float) * q->buff_size);
}
}
}
}
int srslte_softbuffer_tx_init(srslte_softbuffer_tx_t *q, srslte_cell_t cell) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_softbuffer_tx_t));
ret = srslte_ra_tbs_from_idx(26, cell.nof_prb);
if (ret != SRSLTE_ERROR) {
q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1;
q->buffer_b = srslte_vec_malloc(sizeof(uint8_t*) * q->max_cb);
if (!q->buffer_b) {
perror("malloc");
return SRSLTE_ERROR;
}
// FIXME: Use HARQ buffer limitation based on UE category
q->buff_size = cell.nof_prb * MAX_PDSCH_RE(cell.cp) * 6 * 10;
for (uint32_t i=0;i<q->max_cb;i++) {
q->buffer_b[i] = srslte_vec_malloc(sizeof(float) * q->buff_size);
if (!q->buffer_b[i]) {
perror("malloc");
return SRSLTE_ERROR;
}
}
srslte_softbuffer_tx_reset(q);
ret = SRSLTE_SUCCESS;
}
}
return ret;
}
void srslte_softbuffer_tx_free(srslte_softbuffer_tx_t *q) {
if (q) {
if (q->buffer_b) {
for (uint32_t i=0;i<q->max_cb;i++) {
if (q->buffer_b[i]) {
free(q->buffer_b[i]);
}
}
free(q->buffer_b);
}
bzero(q, sizeof(srslte_softbuffer_tx_t));
}
}
void srslte_softbuffer_tx_reset(srslte_softbuffer_tx_t *q) {
int i;
if (q->buffer_b) {
for (i=0;i<q->max_cb;i++) {
if (q->buffer_b[i]) {
bzero(q->buffer_b[i], sizeof(uint8_t) * q->buff_size);
}
}
}
}

@ -35,7 +35,7 @@
#include <math.h>
#include "srslte/phch/uci.h"
#include "srslte/phch/harq.h"
#include "srslte/fec/cbsegm.h"
#include "srslte/fec/convcoder.h"
#include "srslte/fec/crc.h"
#include "srslte/fec/rm_conv.h"
@ -114,22 +114,21 @@ void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t *q) {
}
static uint32_t Q_prime_cqi(uint32_t O, float beta, uint32_t Q_prime_ri, srslte_harq_t *harq) {
uint32_t M_sc = harq->ul_alloc.L_prb * SRSLTE_NRE;
static uint32_t Q_prime_cqi(srslte_pusch_cfg_t *cfg,
uint32_t O, float beta, uint32_t Q_prime_ri)
{
uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 +
harq->cb_segm.C2*harq->cb_segm.K2;
uint32_t K = cfg->cb_segm.C1*cfg->cb_segm.K1 + cfg->cb_segm.C2*cfg->cb_segm.K2;
uint32_t Q_prime = 0;
uint32_t L = (O<11)?0:8;
uint32_t x = 999999;
if (K > 0) {
uint32_t M_sc_init = harq->nof_prb * SRSLTE_NRE;
uint32_t L = (O<11)?0:8;
uint32_t x = (uint32_t) ceilf((float) (O+L)*M_sc_init*harq->nof_symb*beta/K);
Q_prime = SRSLTE_MIN(x, M_sc * harq->nof_symb - Q_prime_ri);
} else {
Q_prime = 12*harq->ul_alloc.L_prb*SRSLTE_NRE - Q_prime_ri;
x = (uint32_t) ceilf((float) (O+L)*cfg->grant.M_sc_init*cfg->grant.nof_symb*beta/K);
}
Q_prime = SRSLTE_MIN(x, cfg->grant.M_sc * cfg->grant.nof_symb - Q_prime_ri);
return Q_prime;
}
@ -217,21 +216,23 @@ int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_b
/* Encode UCI CQI/PMI as described in 5.2.2.6 of 36.212
*/
int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, uint8_t *cqi_data, uint32_t cqi_len, float beta, uint32_t Q_prime_ri,
srslte_harq_t *harq, uint8_t *q_bits)
int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, srslte_pusch_cfg_t *cfg,
uint8_t *cqi_data, uint32_t cqi_len,
float beta, uint32_t Q_prime_ri,
uint8_t *q_bits)
{
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Q_prime = Q_prime_cqi(cqi_len, beta, Q_prime_ri, harq);
uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod);
uint32_t Q_prime = Q_prime_cqi(cfg, cqi_len, beta, Q_prime_ri);
int ret = SRSLTE_ERROR;
if (cqi_len <= 11) {
ret = encode_cqi_short(q, cqi_data, cqi_len, q_bits, Q_prime*Q_m);
ret = encode_cqi_short(q, cqi_data, cqi_len, q_bits, Q_prime*cfg->grant.Qm);
} else {
ret = encode_cqi_long(q, cqi_data, cqi_len, q_bits, Q_prime*Q_m);
ret = encode_cqi_long(q, cqi_data, cqi_len, q_bits, Q_prime*cfg->grant.Qm);
}
if (ret) {
return ret;
@ -242,7 +243,7 @@ int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, uint8_t *cqi_data, ui
/* Inserts UCI-ACK bits into the correct positions in the g buffer before interleaving */
static int uci_ulsch_interleave_ack(uint8_t ack_coded_bits[6], uint32_t ack_q_bit_idx,
uint32_t Q_m, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp,
uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp,
uint8_t *q_bits) {
const uint32_t ack_column_set_norm[4] = {2, 3, 8, 9};
@ -253,9 +254,9 @@ static int uci_ulsch_interleave_ack(uint8_t ack_coded_bits[6], uint32_t ack_q_bi
uint32_t row = H_prime_total/N_pusch_symbs-1-ack_q_bit_idx/4;
uint32_t colidx = (3*ack_q_bit_idx)%4;
uint32_t col = SRSLTE_CP_ISNORM(cp)?ack_column_set_norm[colidx]:ack_column_set_ext[colidx];
for(uint32_t k=0; k<Q_m; k++) {
q_bits[row *Q_m +
(H_prime_total/N_pusch_symbs)*col*Q_m + k] = ack_coded_bits[k];
for(uint32_t k=0; k<Qm; k++) {
q_bits[row *Qm +
(H_prime_total/N_pusch_symbs)*col*Qm + k] = ack_coded_bits[k];
}
return SRSLTE_SUCCESS;
} else {
@ -267,7 +268,7 @@ static int uci_ulsch_interleave_ack(uint8_t ack_coded_bits[6], uint32_t ack_q_bi
/* Inserts UCI-RI bits into the correct positions in the g buffer before interleaving */
static int uci_ulsch_interleave_ri(uint8_t ri_coded_bits[6], uint32_t ri_q_bit_idx,
uint32_t Q_m, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp,
uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp,
uint8_t *q_bits) {
static uint32_t ri_column_set_norm[4] = {1, 4, 7, 10};
@ -278,8 +279,8 @@ static int uci_ulsch_interleave_ri(uint8_t ri_coded_bits[6], uint32_t ri_q_bit_i
uint32_t colidx = (3*ri_q_bit_idx)%4;
uint32_t col = SRSLTE_CP_ISNORM(cp)?ri_column_set_norm[colidx]:ri_column_set_ext[colidx];
printf("r=%d-%d\n",H_prime_total/N_pusch_symbs,1+ri_q_bit_idx/4);
for(uint32_t k=0; k<Q_m; k++) {
q_bits[row *Q_m + (H_prime_total/N_pusch_symbs)*col*Q_m + k] = 10+ri_coded_bits[k];
for(uint32_t k=0; k<Qm; k++) {
q_bits[row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k] = 10+ri_coded_bits[k];
}
return SRSLTE_SUCCESS;
} else {
@ -290,17 +291,15 @@ static int uci_ulsch_interleave_ri(uint8_t ri_coded_bits[6], uint32_t ri_q_bit_i
}
static uint32_t Q_prime_ri_ack(uint32_t O, uint32_t O_cqi, float beta, srslte_harq_t *harq) {
static uint32_t Q_prime_ri_ack(srslte_pusch_cfg_t *cfg,
uint32_t O, uint32_t O_cqi, float beta) {
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t M_sc = harq->ul_alloc.L_prb * SRSLTE_NRE;
uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 +
harq->cb_segm.C2*harq->cb_segm.K2;
uint32_t K = cfg->cb_segm.C1*cfg->cb_segm.K1 + cfg->cb_segm.C2*cfg->cb_segm.K2;
// If not carrying UL-SCH, get Q_prime according to 5.2.4.1
if (K == 0) {
@ -311,19 +310,17 @@ static uint32_t Q_prime_ri_ack(uint32_t O, uint32_t O_cqi, float beta, srslte_ha
}
}
uint32_t M_sc_init = harq->nof_prb * SRSLTE_NRE;
uint32_t x = (uint32_t) ceilf((float) O*M_sc_init*harq->nof_symb*beta/K);
uint32_t x = (uint32_t) ceilf((float) O*cfg->grant.M_sc_init*cfg->grant.nof_symb*beta/K);
uint32_t Q_prime = SRSLTE_MIN(x, 4*M_sc);
uint32_t Q_prime = SRSLTE_MIN(x, 4*cfg->grant.M_sc);
return Q_prime;
}
static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Q_m) {
static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Qm) {
q_encoded_bits[0] = data;
q_encoded_bits[1] = 2;
for (uint32_t i=2;i<Q_m;i++) {
for (uint32_t i=2;i<Qm;i++) {
q_encoded_bits[i] = 3;
}
}
@ -331,23 +328,23 @@ static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Q_m)
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ
*/
int srslte_uci_encode_ack(uint8_t data, uint32_t O_cqi,
float beta, srslte_harq_t *harq,
uint32_t H_prime_total, uint8_t *q_bits)
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits)
{
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod);
uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq);
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
uint8_t q_encoded_bits[6];
encode_ri_ack(data, q_encoded_bits, Q_m);
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ack(q_encoded_bits, i, Q_m, H_prime_total, harq->nof_symb, harq->cell.cp, q_bits);
uci_ulsch_interleave_ack(q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->grant.nof_symb, cfg->cp, q_bits);
}
return (int) Qprime;
@ -357,23 +354,22 @@ int srslte_uci_encode_ack(uint8_t data, uint32_t O_cqi,
/* Encode UCI RI bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit RI
*/
int srslte_uci_encode_ri(uint8_t data, uint32_t O_cqi, float beta,
srslte_harq_t *harq, uint32_t H_prime_total,
int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits)
{
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod);
uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq);
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
uint8_t q_encoded_bits[6];
encode_ri_ack(data, q_encoded_bits, Q_m);
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ri(q_encoded_bits, i, Q_m, H_prime_total, harq->nof_symb, harq->cell.cp, q_bits);
uci_ulsch_interleave_ri(q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->grant.nof_symb, cfg->cp, q_bits);
}
return (int) Qprime;

@ -39,7 +39,7 @@ void usage(char *prog) {
int main(int argc, char **argv) {
srslte_dci_msg_t msg;
srslte_ra_pdsch_t ra_dl;
srslte_ra_dl_dci_t ra_dl;
int len, rlen;
int nof_prb;
int nwords;
@ -91,7 +91,7 @@ int main(int argc, char **argv) {
srslte_dci_msg_type_fprint(stdout, dci_type);
switch (dci_type.type) {
case SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED:
bzero(&ra_dl, sizeof(srslte_ra_pdsch_t));
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
srslte_dci_msg_unpack_pdsch(&msg, &ra_dl, nof_prb, false);
srslte_ra_pdsch_fprint(stdout, &ra_dl, nof_prb);
break;

@ -46,16 +46,14 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
srslte_sch_t dlsch;
uint8_t *trblkin;
srslte_ra_mcs_t mcs;
srslte_ra_dl_alloc_t prb_alloc;
srslte_harq_t harq_process;
uint32_t rv;
srslte_pdsch_cfg_t cfg;
srslte_softbuffer_tx_t softbuffer;
if (nrhs < NOF_INPUTS) {
help();
return;
}
if (srslte_sch_init(&dlsch)) {
mexErrMsgTxt("Error initiating DL-SCH\n");
return;
@ -63,18 +61,14 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_cell_t cell;
cell.nof_prb = 100;
cell.id=1;
if (srslte_harq_init(&harq_process, cell)) {
mexErrMsgTxt("Error initiating HARQ\n");
return;
}
mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
if (mcs.tbs == 0) {
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
if (cfg.grant.mcs.tbs == 0) {
mexErrMsgTxt("Error trblklen is zero\n");
return;
}
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) {
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &cfg.rv)) {
mexErrMsgTxt("Field RV not found in dlsch config\n");
return;
}
@ -82,36 +76,42 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) {
mcs.mod = SRSLTE_MOD_QPSK;
cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
cfg.grant.Qm = 2;
} else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM;
cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
cfg.grant.Qm = 4;
} else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM;
cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
cfg.grant.Qm = 6;
} else {
mexErrMsgTxt("Unknown modulation\n");
return;
}
mxFree(mod_str);
if (srslte_harq_setup_dl(&harq_process, mcs, rv, 0, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
mexErrMsgTxt("Error initiating DL-SCH soft buffer\n");
return;
}
harq_process.nof_bits = mxGetScalar(OUTLEN);
uint8_t *e_bits = srslte_vec_malloc(harq_process.nof_bits* sizeof(uint8_t));
cfg.grant.nof_bits = mxGetScalar(OUTLEN);
uint8_t *e_bits = srslte_vec_malloc(cfg.grant.nof_bits * sizeof(uint8_t));
if (!e_bits) {
return;
}
if (srslte_dlsch_encode(&dlsch, &harq_process, trblkin, e_bits)) {
if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
mexErrMsgTxt("Error computing CB segmentation\n");
return;
}
if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) {
mexErrMsgTxt("Error encoding TB\n");
return;
}
if (nlhs >= 1) {
mexutils_write_uint8(e_bits, &plhs[0], harq_process.nof_bits, 1);
mexutils_write_uint8(e_bits, &plhs[0], cfg.grant.nof_bits, 1);
}
srslte_sch_free(&dlsch);

@ -200,7 +200,7 @@ void base_free() {
}
int main(int argc, char **argv) {
srslte_ra_pdsch_t ra_dl;
srslte_ra_dl_dci_t ra_dl;
int i;
int frame_cnt;
int ret;
@ -264,7 +264,7 @@ int main(int argc, char **argv) {
srslte_dci_msg_type_fprint(stdout, type);
switch(type.type) {
case SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED:
bzero(&ra_dl, sizeof(srslte_ra_pdsch_t));
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
if (srslte_dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb, rnti != SRSLTE_SIRNTI)) {
fprintf(stderr, "Can't unpack PDSCH message\n");
} else {

@ -109,7 +109,7 @@ int main(int argc, char **argv) {
srslte_pdcch_t pdcch;
srslte_dci_msg_t dci_tx[2], dci_rx[2], dci_tmp;
srslte_dci_location_t dci_locations[2];
srslte_ra_pdsch_t ra_dl;
srslte_ra_dl_dci_t ra_dl;
srslte_regs_t regs;
int i, j;
cf_t *ce[SRSLTE_MAX_PORTS];
@ -160,7 +160,7 @@ int main(int argc, char **argv) {
}
nof_dcis = 2;
bzero(&ra_dl, sizeof(srslte_ra_pdsch_t));
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
ra_dl.harq_process = 0;
ra_dl.mcs_idx = 5;
ra_dl.ndi = 0;

@ -57,13 +57,8 @@ uint32_t sf_idx = 0;
srslte_dci_format_t dci_format = SRSLTE_DCI_FORMAT1A;
srslte_filesource_t fsrc;
srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch;
srslte_harq_t harq_process;
cf_t *input_buffer, *fft_buffer, *ce[SRSLTE_MAX_PORTS];
srslte_regs_t regs;
srslte_ofdm_t fft;
srslte_chest_dl_t chest;
srslte_ue_dl_t ue_dl;
cf_t *input_buffer;
void usage(char *prog) {
printf("Usage: %s [rovfcenmps] -i input_file\n", prog);
@ -132,7 +127,6 @@ void parse_args(int argc, char **argv) {
}
int base_init() {
int i;
if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
fprintf(stderr, "Error opening file %s\n", input_file_name);
@ -147,98 +141,31 @@ int base_init() {
exit(-1);
}
fft_buffer = malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
if (!fft_buffer) {
perror("malloc");
return -1;
}
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
if (!ce[i]) {
perror("malloc");
return -1;
}
}
if (srslte_chest_dl_init(&chest, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) {
fprintf(stderr, "Error initializing FFT\n");
return -1;
}
if (srslte_regs_init(&regs, cell)) {
fprintf(stderr, "Error initiating regs\n");
return -1;
}
if (srslte_regs_set_cfi(&regs, cfi)) {
fprintf(stderr, "Error setting CFI %d\n", cfi);
if (srslte_ue_dl_init(&ue_dl, cell)) {
fprintf(stderr, "Error initializing UE DL\n");
return -1;
}
if (srslte_pdcch_init(&pdcch, &regs, cell)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdsch_init(&pdsch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
srslte_pdsch_set_rnti(&pdsch, rnti);
if (srslte_harq_init(&harq_process, cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
exit(-1);
}
srslte_ue_dl_set_rnti(&ue_dl, rnti);
DEBUG("Memory init OK\n",0);
return 0;
}
void base_free() {
int i;
srslte_filesource_free(&fsrc);
free(input_buffer);
free(fft_buffer);
srslte_filesource_free(&fsrc);
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
free(ce[i]);
}
srslte_chest_dl_free(&chest);
srslte_ofdm_rx_free(&fft);
srslte_pdcch_free(&pdcch);
srslte_pdsch_free(&pdsch);
srslte_harq_free(&harq_process);
srslte_regs_free(&regs);
srslte_ue_dl_free(&ue_dl);
free(input_buffer);
}
int main(int argc, char **argv) {
srslte_ra_pdsch_t ra_dl;
int i;
int nof_frames;
int ret;
uint8_t *data;
srslte_dci_location_t locations[MAX_CANDIDATES];
uint32_t nof_locations = 0;
srslte_dci_msg_t dci_msg;
data = malloc(100000);
if (argc < 3) {
usage(argv[0]);
exit(-1);
}
parse_args(argc,argv);
if (base_init()) {
@ -246,67 +173,30 @@ int main(int argc, char **argv) {
exit(-1);
}
if (rnti == SRSLTE_SIRNTI) {
INFO("Initializing common search space for SI-RNTI\n",0);
nof_locations = srslte_pdcch_common_locations(&pdcch, locations, MAX_CANDIDATES, cfi);
}
uint8_t *data = malloc(100000);
ret = -1;
nof_frames = 0;
do {
srslte_filesource_read(&fsrc, input_buffer, flen);
INFO("Reading %d samples sub-frame %d\n", flen, sf_idx);
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer);
/* Get channel estimates for each port */
srslte_chest_dl_estimate(&chest, fft_buffer, ce, sf_idx);
if (rnti != SRSLTE_SIRNTI) {
INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti);
nof_locations = srslte_pdcch_ue_locations(&pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti);
}
uint16_t crc_rem = 0;
if (srslte_pdcch_extract_llr(&pdcch, fft_buffer, ce, srslte_chest_dl_get_noise_estimate(&chest), sf_idx, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return -1;
ret = srslte_ue_dl_decode(&ue_dl, input_buffer, data, sf_idx);
if(ret > 0) {
printf("PDSCH Decoded OK!\n");
} else if (ret == 0) {
printf("No DCI grant found\n");
} else if (ret < 0) {
printf("Error decoding PDSCH\n");
}
for (i=0;i<nof_locations && crc_rem != rnti;i++) {
if (srslte_pdcch_decode_msg(&pdcch, &dci_msg, &locations[i], dci_format, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return -1;
}
}
if (crc_rem == rnti) {
if (srslte_dci_msg_to_ra_dl(&dci_msg, rnti, cell, cfi, &ra_dl)) {
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
goto goout;
}
if (ra_dl.mcs.tbs > 0) {
if (srslte_harq_setup_dl(&harq_process, ra_dl.mcs, ra_dl.rv_idx, sf_idx, &ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto goout;
}
if (srslte_pdsch_decode(&pdsch, &harq_process, fft_buffer, ce, srslte_chest_dl_get_noise_estimate(&chest), data)) {
fprintf(stderr, "Error decoding PDSCH\n");
goto goout;
} else {
printf("PDSCH Decoded OK!\n");
}
} else {
printf("Received DCI with no resource allocation\n");
}
sf_idx = (sf_idx+1)%10;
}
sf_idx = (sf_idx+1)%10;
nof_frames++;
} while (nof_frames <= max_frames);
} while (nof_frames <= max_frames && ret == 0);
ret = 0;
goout:
base_free();
exit(ret);
if (ret > 0) {
exit(0);
} else {
exit(-1);
}
}

@ -127,45 +127,49 @@ int main(int argc, char **argv) {
uint32_t i, j;
uint8_t *data = NULL;
cf_t *ce[SRSLTE_MAX_PORTS];
uint32_t nof_re;
cf_t *slot_symbols[SRSLTE_MAX_PORTS];
int ret = -1;
struct timeval t[3];
srslte_ra_mcs_t mcs;
srslte_ra_dl_alloc_t prb_alloc;
srslte_harq_t harq_process;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_tx_t softbuffer_tx;
srslte_softbuffer_rx_t softbuffer_rx;
uint32_t rv;
parse_args(argc,argv);
bzero(&pdsch, sizeof(srslte_pdsch_t));
bzero(&harq_process, sizeof(srslte_harq_t));
bzero(&pdsch_cfg, sizeof(srslte_pdsch_cfg_t));
bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE;
pdsch_cfg.grant.nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE;
mcs.mod = modulation;
pdsch_cfg.grant.mcs.mod = modulation;
prb_alloc.slot[0].nof_prb = cell.nof_prb;
for (i=0;i<prb_alloc.slot[0].nof_prb;i++) {
prb_alloc.slot[0].prb_idx[i] = true;
pdsch_cfg.grant.nof_prb = cell.nof_prb;
for (i=0;i<pdsch_cfg.grant.nof_prb;i++) {
pdsch_cfg.grant.prb_idx[0][i] = true;
}
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(srslte_ra_prb_slot_t));
memcpy(&pdsch_cfg.grant.prb_idx[1], &pdsch_cfg.grant.prb_idx[0], SRSLTE_MAX_PRB * sizeof(bool));
srslte_dl_dci_to_grant_nof_re(&pdsch_cfg.grant, cell, pdsch_cfg.sf_idx, cell.nof_prb<10?(cfi+1):cfi);
// Fill rest of grant structure
pdsch_cfg.grant.lstart = cell.nof_prb<10?(cfi+1):cfi;
pdsch_cfg.grant.nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-pdsch_cfg.grant.lstart;
pdsch_cfg.grant.Qm = srslte_mod_bits_x_symbol(pdsch_cfg.grant.mcs.mod);
pdsch_cfg.grant.nof_bits = pdsch_cfg.grant.nof_re * pdsch_cfg.grant.Qm;
srslte_ra_dl_alloc_re(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
/* init memory */
for (i=0;i<cell.nof_ports;i++) {
ce[i] = malloc(sizeof(cf_t) * nof_re);
ce[i] = malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!ce[i]) {
perror("malloc");
goto quit;
}
for (j=0;j<nof_re;j++) {
for (j=0;j<pdsch_cfg.grant.nof_re;j++) {
ce[i][j] = 1;
}
slot_symbols[i] = calloc(sizeof(cf_t) , nof_re);
slot_symbols[i] = calloc(sizeof(cf_t) , SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!slot_symbols[i]) {
perror("malloc");
goto quit;
@ -185,33 +189,35 @@ int main(int argc, char **argv) {
srslte_pdsch_set_rnti(&pdsch, 1234);
if (srslte_harq_init(&harq_process, cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
if (srslte_softbuffer_tx_init(&softbuffer_tx, cell)) {
fprintf(stderr, "Error initiating TX soft buffer\n");
goto quit;
}
if (srslte_softbuffer_rx_init(&softbuffer_rx, cell)) {
fprintf(stderr, "Error initiating RX soft buffer\n");
goto quit;
}
for (mcs.tbs = tbs;mcs.tbs<=tbs+nof_tbs;mcs.tbs++) {
for (pdsch_cfg.grant.mcs.tbs = tbs;pdsch_cfg.grant.mcs.tbs<=tbs+nof_tbs;pdsch_cfg.grant.mcs.tbs++) {
if (SRSLTE_VERBOSE_ISNONE()) {
printf("Decoding TBS: %d\r",mcs.tbs);
printf("Decoding TBS: %d\r",pdsch_cfg.grant.mcs.tbs);
}
for (i=0;i<mcs.tbs;i++) {
for (i=0;i<pdsch_cfg.grant.mcs.tbs;i++) {
data[i] = rand()%2;
}
for (rv=0;rv<=rv_idx;rv++) {
if (srslte_harq_setup_dl(&harq_process, mcs, rv, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
srslte_cbsegm(&pdsch_cfg.cb_segm, pdsch_cfg.grant.mcs.tbs);
if (srslte_pdsch_encode(&pdsch, &harq_process, data, slot_symbols)) {
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
goto quit;
}
/* combine outputs */
for (i=0;i<cell.nof_ports;i++) {
for (j=0;j<nof_re;j++) {
for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
if (i > 0) {
slot_symbols[0][j] += slot_symbols[i][j];
}
@ -220,16 +226,16 @@ int main(int argc, char **argv) {
}
gettimeofday(&t[1], NULL);
int r = srslte_pdsch_decode(&pdsch, &harq_process, slot_symbols[0], ce, 0, data);
int r = srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, data);
gettimeofday(&t[2], NULL);
get_time_interval(t);
if (r) {
printf("Error decoding TBS: %d\n", mcs.tbs);
printf("Error decoding TBS: %d\n", pdsch_cfg.grant.mcs.tbs);
ret = -1;
goto quit;
} else {
if (nof_tbs == 0) {
printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) mcs.tbs/t[0].tv_usec);
printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) pdsch_cfg.grant.mcs.tbs/t[0].tv_usec);
}
}
}
@ -237,7 +243,8 @@ int main(int argc, char **argv) {
ret = 0;
quit:
srslte_pdsch_free(&pdsch);
srslte_harq_free(&harq_process);
srslte_softbuffer_tx_free(&softbuffer_tx);
srslte_softbuffer_rx_free(&softbuffer_rx);
for (i=0;i<cell.nof_ports;i++) {
if (ce[i]) {

@ -54,20 +54,20 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_pdsch_t pdsch;
srslte_chest_dl_t chest;
srslte_ofdm_t fft;
uint32_t cfi, sf_idx;
cf_t *input_fft, *input_signal;
int nof_re;
srslte_ra_mcs_t mcs;
srslte_ra_dl_alloc_t dl_alloc;
srslte_harq_t harq_process;
uint32_t rv;
srslte_pdsch_cfg_t cfg;
srslte_softbuffer_rx_t softbuffer;
uint32_t rnti32;
uint32_t cfi;
if (nrhs < NOF_INPUTS) {
help();
return;
}
bzero(&cfg, sizeof(srslte_pdsch_cfg_t));
if (mexutils_read_cell(ENBCFG, &cell)) {
help();
return;
@ -82,7 +82,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
help();
return;
}
if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &sf_idx)) {
if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &cfg.sf_idx)) {
help();
return;
}
@ -93,8 +93,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
srslte_pdsch_set_rnti(&pdsch, (uint16_t) (rnti32 & 0xffff));
if (srslte_harq_init(&harq_process, cell)) {
mexErrMsgTxt("Error initiating HARQ process\n");
if (srslte_softbuffer_rx_init(&softbuffer, cell)) {
mexErrMsgTxt("Error initiating soft buffer\n");
return;
}
@ -108,16 +108,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE;
mcs.tbs = mxGetScalar(TBS);
if (mcs.tbs == 0) {
cfg.grant.mcs.tbs = mxGetScalar(TBS);
if (cfg.grant.mcs.tbs == 0) {
mexErrMsgTxt("Error trblklen is zero\n");
return;
}
if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
mexErrMsgTxt("Error computing CB segmentation\n");
return;
}
if (mexutils_read_uint32_struct(PDSCHCFG, "RV", &rv)) {
if (mexutils_read_uint32_struct(PDSCHCFG, "RV", &cfg.rv)) {
mexErrMsgTxt("Field RV not found in pdsch config\n");
return;
}
@ -125,11 +128,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) {
mcs.mod = SRSLTE_MOD_QPSK;
cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM;
cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM;
cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
} else {
mexErrMsgTxt("Unknown modulation\n");
return;
@ -146,27 +149,28 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
// Only localized PRB supported
dl_alloc.slot[0].nof_prb = mexutils_read_f(p, &prbset);
cfg.grant.nof_prb = mexutils_read_f(p, &prbset);
for (i=0;i<cell.nof_prb;i++) {
dl_alloc.slot[0].prb_idx[i] = false;
for (int j=0;j<dl_alloc.slot[0].nof_prb && !dl_alloc.slot[0].prb_idx[i];j++) {
cfg.grant.prb_idx[0][i] = false;
for (int j=0;j<cfg.grant.nof_prb && !cfg.grant.prb_idx[0][i];j++) {
if ((int) prbset[j] == i) {
dl_alloc.slot[0].prb_idx[i] = true;
cfg.grant.prb_idx[0][i] = true;
}
}
}
memcpy(&dl_alloc.slot[1], &dl_alloc.slot[0], sizeof(srslte_ra_prb_slot_t));
memcpy(&cfg.grant.prb_idx[1], &cfg.grant.prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool));
free(prbset);
srslte_ra_dl_alloc_re(&dl_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
srslte_dl_dci_to_grant_nof_re(&cfg.grant, cell, cfg.sf_idx, cell.nof_prb<10?(cfi+1):cfi);
if (srslte_harq_setup_dl(&harq_process, mcs, rv, sf_idx, &dl_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
// Fill rest of grant structure
cfg.grant.lstart = cell.nof_prb<10?(cfi+1):cfi;
cfg.grant.nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-cfg.grant.lstart;
cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod);
cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm;
/** Allocate input buffers */
if (mexutils_read_cf(INPUT, &input_signal) < 0) {
mexErrMsgTxt("Error reading input signal\n");
@ -174,7 +178,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
// Set Channel estimates to 1.0 (ignore fading)
cf_t *ce[SRSLTE_MAX_PORTS];
for (i=0;i<cell.nof_ports;i++) {
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
@ -195,7 +198,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
if (cearray_ptr)
free(cearray_ptr);
} else {
srslte_chest_dl_estimate(&chest, input_fft, ce, sf_idx);
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
}
float noise_power;
if (nrhs > NOF_INPUTS + 1) {
@ -204,28 +207,28 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
}
uint8_t *data = malloc(sizeof(uint8_t) * mcs.tbs);
uint8_t *data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs);
if (!data) {
return;
}
int r = srslte_pdsch_decode(&pdsch, &harq_process, input_fft, ce, noise_power, data);
int r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data);
if (nlhs >= 1) {
plhs[0] = mxCreateLogicalScalar(r == 0);
}
if (nlhs >= 2) {
mexutils_write_uint8(data, &plhs[1], mcs.tbs, 1);
mexutils_write_uint8(data, &plhs[1], cfg.grant.mcs.tbs, 1);
}
if (nlhs >= 3) {
mexutils_write_cf(pdsch.symbols[0], &plhs[2], harq_process.dl_alloc.re_sf[sf_idx], 1);
mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.grant.nof_re, 1);
}
if (nlhs >= 4) {
mexutils_write_cf(pdsch.d, &plhs[3], harq_process.dl_alloc.re_sf[sf_idx], 1);
mexutils_write_cf(pdsch.d, &plhs[3], cfg.grant.nof_re, 1);
}
if (nlhs >= 5) {
mexutils_write_f(pdsch.e, &plhs[4], harq_process.dl_alloc.re_sf[sf_idx] * srslte_mod_bits_x_symbol(mcs.mod), 1);
mexutils_write_f(pdsch.e, &plhs[4], cfg.grant.nof_bits, 1);
}
srslte_chest_dl_free(&chest);

@ -261,7 +261,7 @@ int main(int argc, char **argv) {
exit(-1);
}
INFO("%d/%d, ack_rx: %d, ns: %d, distance: %d\n",
INFO("%d/%d, ack_rx: %d, ns: %d, distance: %f\n",
ngroup, nseq, ack_rx, numsubframe, distance);
}
}

@ -186,7 +186,7 @@ int main(int argc, char **argv) {
printf("Error decoding ACK\n");
exit(-1);
}
INFO("%d/%d, ack_tx: %d, ack_rx: %d, ns: %d, distance: %d\n",
INFO("%d/%d, ack_tx: %d, ack_rx: %d, ns: %d, distance: %f\n",
ngroup, nseq, ack[ngroup][nseq], ack_rx, nsf, distance);
if (ack[ngroup][nseq] != ack_rx) {
printf("Invalid received ACK: %d!=%d\n", ack[ngroup][nseq], ack_rx);

@ -80,20 +80,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
uint32_t sf_idx=0;
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
srslte_pusch_cfg_t cfg;
bzero(&cfg, sizeof(srslte_pusch_cfg_t));
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &cfg.sf_idx)) {
mexErrMsgTxt("Field NSubframe not found in UE config\n");
return;
}
srslte_ra_mcs_t mcs;
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) {
mcs.mod = SRSLTE_MOD_QPSK;
cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM;
cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM;
cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
} else {
mexErrMsgTxt("Unknown modulation\n");
return;
@ -108,27 +107,32 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Error field PRBSet not found\n");
return;
}
srslte_ra_ul_alloc_t prb_alloc;
bzero(&prb_alloc, sizeof(srslte_ra_ul_alloc_t));
prb_alloc.L_prb = mexutils_read_f(p, &prbset);
prb_alloc.n_prb[0] = prbset[0];
prb_alloc.n_prb[1] = prbset[0];
cfg.grant.L_prb = mexutils_read_f(p, &prbset);
cfg.grant.n_prb[0] = prbset[0];
cfg.grant.n_prb[1] = prbset[0];
cfg.grant.lstart = 0;
cfg.grant.nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1);
cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE;
cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be?
cfg.grant.nof_re = cfg.grant.nof_symb*cfg.grant.M_sc;
cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod);
cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm;
free(prbset);
mexPrintf("L_prb: %d, n_prb: %d\n", prb_alloc.L_prb, prb_alloc.n_prb[2*sf_idx]);
mexPrintf("L_prb: %d, n_prb: %d\n", cfg.grant.L_prb, cfg.grant.n_prb[0]);
uint8_t *trblkin = NULL;
mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
srslte_harq_t harq_process;
if (srslte_harq_init(&harq_process, cell)) {
mexErrMsgTxt("Error initiating HARQ process\n");
srslte_softbuffer_tx_t softbuffer;
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
mexErrMsgTxt("Error initiating soft buffer\n");
return;
}
if (srslte_harq_setup_ul(&harq_process, mcs, 0, sf_idx, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
mexErrMsgTxt("Error computing CB segmentation\n");
return;
}
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
@ -156,36 +160,39 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
free(tmp);
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetCQI", &uci_data.I_offset_cqi)) {
float beta;
if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) {
uci_data.I_offset_cqi = 7;
} else {
uci_data.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta);
}
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetRI", &uci_data.I_offset_ri)) {
if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) {
uci_data.I_offset_ri = 2;
} else {
uci_data.I_offset_ri = srslte_sch_find_Ioffset_ri(beta);
}
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetACK", &uci_data.I_offset_ack)) {
if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) {
uci_data.I_offset_ack = 0;
} else {
uci_data.I_offset_ack = srslte_sch_find_Ioffset_ack(beta);
}
mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", mcs.tbs,
mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", cfg.grant.mcs.tbs,
uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ack, uci_data.uci_ri_len, uci_data.uci_ri);
mexPrintf("NofRE: %d, NofBits: %d, TBS: %d\n", harq_process.nof_re, harq_process.nof_bits, harq_process.mcs.tbs);
int r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols);
mexPrintf("I_cqi: %d, I_ri: %d, I_ack=%d\n", uci_data.I_offset_cqi, uci_data.I_offset_ri, uci_data.I_offset_ack);
mexPrintf("NofRE: %d, NofBits: %d, TBS: %d\n", cfg.grant.nof_re, cfg.grant.nof_bits, cfg.grant.mcs.tbs);
int r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols);
if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n");
return;
}
uint32_t rv=0;
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) {
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &cfg.rv)) {
mexErrMsgTxt("Field RV not found in pdsch config\n");
return;
}
if (rv > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv, sf_idx, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols);
if (cfg.rv > 0) {
r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols);
if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n");
return;
@ -210,7 +217,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1);
}
if (nlhs >= 3) {
mexutils_write_cf(pusch.z, &plhs[2], harq_process.nof_re, 1);
mexutils_write_cf(pusch.z, &plhs[2], cfg.grant.nof_re, 1);
}
srslte_pusch_free(&pusch);
free(trblkin);

@ -135,29 +135,49 @@ int main(int argc, char **argv) {
cf_t *sf_symbols = NULL;
int ret = -1;
struct timeval t[3];
srslte_ra_mcs_t mcs;
srslte_ra_ul_alloc_t prb_alloc;
srslte_harq_t harq_process;
srslte_pusch_cfg_t cfg;
srslte_softbuffer_tx_t softbuffer;
parse_args(argc,argv);
mcs.tbs = tbs;
mcs.mod = modulation;
bzero(&prb_alloc, sizeof(srslte_ra_ul_alloc_t));
bzero(&cfg, sizeof(srslte_pusch_cfg_t));
srslte_ra_ul_dci_t dci;
dci.freq_hop_fl = freq_hop;
if (riv < 0) {
dci.type2_alloc.L_crb = L_prb;
dci.type2_alloc.RB_start = n_prb;
} else {
srslte_ra_type2_from_riv((uint32_t) riv, &dci.type2_alloc.L_crb, &dci.type2_alloc.RB_start, cell.nof_prb, cell.nof_prb);
}
cfg.grant.mcs.tbs = tbs;
cfg.grant.mcs.mod = modulation;
// Compute PRB allocation
if (!srslte_ul_dci_to_grant_prb_allocation(&dci, &cfg.grant, 0, cell.nof_prb)) {
cfg.grant.lstart = 0;
cfg.grant.nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1);
cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE;
cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be?
cfg.grant.nof_re = cfg.grant.nof_symb*cfg.grant.M_sc;
cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod);
cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm;
}
if (srslte_pusch_init(&pusch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
srslte_pusch_set_rnti(&pusch, 1234);
if (srslte_harq_init(&harq_process, cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto quit;
}
printf("Encoding rv_idx=%d\n",rv_idx);
cfg.rv = 0;
cfg.sf_idx = subframe;
uint8_t tmp[20];
for (uint32_t i=0;i<20;i++) {
@ -167,28 +187,18 @@ int main(int argc, char **argv) {
bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_data.I_offset_cqi = 7;
uci_data.I_offset_ri = 2;
uci_data.I_offset_ack = 0;
uci_data.I_offset_ack = 4;
uci_data.uci_cqi_len = 0;
uci_data.uci_cqi_len = 8;
uci_data.uci_ri_len = 0;
uci_data.uci_ack_len = 0;
uci_data.uci_ack_len = 1;
uci_data.uci_cqi = tmp;
uci_data.uci_ri = 1;
uci_data.uci_ack = 1;
uci_data.uci_ri = 0;
uci_data.uci_ack = 0;
srslte_ra_pusch_t dci;
dci.freq_hop_fl = freq_hop;
if (riv < 0) {
dci.type2_alloc.L_crb = L_prb;
dci.type2_alloc.RB_start = n_prb;
} else {
srslte_ra_type2_from_riv((uint32_t) riv, &dci.type2_alloc.L_crb, &dci.type2_alloc.RB_start, cell.nof_prb, cell.nof_prb);
}
srslte_ra_ul_alloc(&prb_alloc, &dci, 0, cell.nof_prb);
if (srslte_harq_setup_ul(&harq_process, mcs, 0, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
fprintf(stderr, "Error configuring CB segmentation\n");
goto quit;
}
srslte_pusch_hopping_cfg_t ul_hopping;
@ -206,34 +216,29 @@ int main(int argc, char **argv) {
goto quit;
}
data = malloc(sizeof(uint8_t) * mcs.tbs);
data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs);
if (!data) {
perror("malloc");
goto quit;
}
for (uint32_t i=0;i<mcs.tbs;i++) {
for (uint32_t i=0;i<cfg.grant.mcs.tbs;i++) {
data[i] = 1;
}
if (srslte_pusch_uci_encode(&pusch, &harq_process, data, uci_data, sf_symbols)) {
if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, data, uci_data, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
if (rv_idx > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv_idx, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
if (srslte_pusch_uci_encode(&pusch, &harq_process, data, uci_data, sf_symbols)) {
cfg.rv = rv_idx;
if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, data, uci_data, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
}
cf_t *scfdma = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
bzero(scfdma, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_ofdm_t fft;
@ -251,13 +256,13 @@ int main(int argc, char **argv) {
ret = -1;
goto quit;
} else {
printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) mcs.tbs/t[0].tv_usec);
printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) cfg.grant.mcs.tbs/t[0].tv_usec);
}
ret = 0;
quit:
srslte_pusch_free(&pusch);
srslte_harq_free(&harq_process);
srslte_softbuffer_tx_free(&softbuffer);
if (sf_symbols) {
free(sf_symbols);

@ -48,17 +48,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
srslte_sch_t ulsch;
uint8_t *trblkin;
srslte_ra_mcs_t mcs;
srslte_ra_ul_alloc_t prb_alloc;
srslte_harq_t harq_process;
uint32_t rv;
srslte_pusch_cfg_t cfg;
srslte_softbuffer_tx_t softbuffer;
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
uint32_t rv;
if (nrhs < NOF_INPUTS) {
help();
return;
}
bzero(&cfg, sizeof(srslte_pusch_cfg_t));
if (srslte_sch_init(&ulsch)) {
mexErrMsgTxt("Error initiating ULSCH\n");
return;
@ -67,12 +68,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cell.nof_prb = 100;
cell.id=1;
cell.cp=SRSLTE_CP_NORM;
if (srslte_harq_init(&harq_process, cell)) {
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
mexErrMsgTxt("Error initiating HARQ\n");
return;
}
mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &uci_data.uci_cqi);
uint8_t *tmp;
@ -87,7 +89,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
free(tmp);
mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d, RI_len: %d\n", mcs.tbs,
mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d, RI_len: %d\n", cfg.grant.mcs.tbs,
uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ri_len);
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) {
@ -95,24 +97,31 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetCQI", &uci_data.I_offset_cqi)) {
float beta;
if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) {
uci_data.I_offset_cqi = 7;
} else {
uci_data.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta);
}
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetRI", &uci_data.I_offset_ri)) {
if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) {
uci_data.I_offset_ri = 2;
} else {
uci_data.I_offset_ri = srslte_sch_find_Ioffset_ri(beta);
}
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetACK", &uci_data.I_offset_ack)) {
if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) {
uci_data.I_offset_ack = 0;
} else {
uci_data.I_offset_ack = srslte_sch_find_Ioffset_ack(beta);
}
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) {
mcs.mod = SRSLTE_MOD_QPSK;
cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM;
cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM;
cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
} else {
mexErrMsgTxt("Unknown modulation\n");
return;
@ -128,49 +137,56 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
prb_alloc.L_prb = mexutils_read_f(p, &prbset);
prb_alloc.n_prb[0] = prbset[0];
prb_alloc.n_prb[1] = prbset[0];
cfg.grant.L_prb = mexutils_read_f(p, &prbset);
cfg.grant.n_prb[0] = prbset[0];
cfg.grant.n_prb[1] = prbset[0];
free(prbset);
mexPrintf("Q_m: %d, NPRB: %d, RV: %d\n", srslte_mod_bits_x_symbol(mcs.mod), prb_alloc.L_prb, rv);
cfg.grant.L_prb = mexutils_read_f(p, &prbset);
cfg.grant.n_prb[0] = prbset[0];
cfg.grant.n_prb[1] = prbset[0];
cfg.grant.lstart = 0;
cfg.grant.nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1);
cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE;
cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be?
cfg.grant.nof_re = cfg.grant.nof_symb*cfg.grant.M_sc;
cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod);
cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm;
if (srslte_harq_setup_ul(&harq_process, mcs, 0, 0, &prb_alloc)) {
mexPrintf("Q_m: %d, NPRB: %d, RV: %d\n", srslte_mod_bits_x_symbol(cfg.grant.mcs.mod), cfg.grant.L_prb, cfg.rv);
if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
uint8_t *q_bits = srslte_vec_malloc(harq_process.nof_bits * sizeof(uint8_t));
uint8_t *q_bits = srslte_vec_malloc(cfg.grant.nof_bits * sizeof(uint8_t));
if (!q_bits) {
return;
}
uint8_t *g_bits = srslte_vec_malloc(harq_process.nof_bits * sizeof(uint8_t));
uint8_t *g_bits = srslte_vec_malloc(cfg.grant.nof_bits * sizeof(uint8_t));
if (!g_bits) {
return;
}
if (srslte_ulsch_uci_encode(&ulsch, &harq_process, trblkin, uci_data, g_bits, q_bits))
if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits))
{
mexErrMsgTxt("Error encoding TB\n");
return;
}
if (rv > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv, 0, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
if (srslte_ulsch_uci_encode(&ulsch, &harq_process, trblkin, uci_data, g_bits, q_bits)) {
cfg.rv = rv;
if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits)) {
mexErrMsgTxt("Error encoding TB\n");
return;
}
}
if (nlhs >= 1) {
mexutils_write_uint8(q_bits, &plhs[0], harq_process.nof_bits, 1);
mexutils_write_uint8(q_bits, &plhs[0], cfg.grant.nof_bits, 1);
}
srslte_sch_free(&ulsch);
srslte_harq_free(&harq_process);
srslte_softbuffer_tx_free(&softbuffer);
free(trblkin);
free(g_bits);

@ -286,7 +286,7 @@ int main(int argc, char **argv) {
frame_cnt++;
printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, "
"FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f\%\r",
"FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r",
frame_cnt,
peak_idx,
peak_value, mean_peak,

@ -296,7 +296,7 @@ int main(int argc, char **argv) {
frame_cnt++;
printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, "
"FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f\%\r",
"FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r",
frame_cnt,
peak_idx,
peak_value, mean_peak,

@ -84,11 +84,9 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit;
}
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
if (srslte_harq_init(&q->harq_process[i], q->cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
goto clean_exit;
}
if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols) {
@ -125,9 +123,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
srslte_phich_free(&q->phich);
srslte_pdcch_free(&q->pdcch);
srslte_pdsch_free(&q->pdsch);
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
srslte_harq_free(&q->harq_process[i]);
}
srslte_softbuffer_rx_free(&q->softbuffer);
if (q->sf_symbols) {
free(q->sf_symbols);
}
@ -136,9 +132,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
free(q->ce[i]);
}
}
bzero(q, sizeof(srslte_ue_dl_t));
}
}
@ -152,7 +146,8 @@ void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) {
}
void srslte_ue_dl_reset(srslte_ue_dl_t *q) {
srslte_harq_reset(&q->harq_process[0]);
srslte_softbuffer_rx_reset(&q->softbuffer);
bzero(&q->pdsch_cfg, sizeof(srslte_pdsch_cfg_t));
}
srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1,SRSLTE_DCI_FORMAT1A}; // SRSLTE_DCI_FORMAT1B should go here also
@ -212,22 +207,26 @@ int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_
int ret = SRSLTE_ERROR;
q->nof_detected++;
if (srslte_dci_msg_to_ra_dl(dci_msg, rnti, q->cell, cfi, &q->ra_dl)) {
srslte_ra_dl_dci_t dl_dci;
if (srslte_dci_msg_to_dl_grant(dci_msg, rnti, q->cell, cfi, sf_idx, &dl_dci, &q->pdsch_cfg.grant)) {
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
return SRSLTE_ERROR;
}
if (rnti != SRSLTE_SIRNTI) {
rvidx = q->ra_dl.rv_idx;
if (srslte_cbsegm(&q->pdsch_cfg.cb_segm, q->pdsch_cfg.grant.mcs.tbs)) {
fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", q->pdsch_cfg.grant.mcs.tbs);
return SRSLTE_ERROR;
}
if (srslte_harq_setup_dl(&q->harq_process[0], q->ra_dl.mcs, rvidx, sf_idx, &q->ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return SRSLTE_ERROR;
q->pdsch_cfg.sf_idx = sf_idx;
if (rnti == SRSLTE_SIRNTI) {
q->pdsch_cfg.rv = rvidx;
} else {
q->pdsch_cfg.rv = dl_dci.rv_idx;
}
if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) {
ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->harq_process[0], q->sf_symbols,
q->ce, 0,
rnti, data);
if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) {
ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer,
q->sf_symbols, q->ce, 0, rnti, data);
if (ret == SRSLTE_ERROR) {
q->pkt_errors++;
@ -236,7 +235,7 @@ int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_
} else if (ret == SRSLTE_SUCCESS) {
if (SRSLTE_VERBOSE_ISINFO()) {
INFO("Decoded Message: ", 0);
srslte_vec_fprint_hex(stdout, data, q->ra_dl.mcs.tbs);
srslte_vec_fprint_hex(stdout, data, q->pdsch_cfg.grant.mcs.tbs);
}
}
q->pkts_total++;
@ -317,7 +316,7 @@ int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, u
}
if (found_dci == 1 && ret == SRSLTE_SUCCESS) {
return q->ra_dl.mcs.tbs;
return q->pdsch_cfg.grant.mcs.tbs;
} else {
return 0;
}

@ -39,7 +39,7 @@
int srslte_ue_ul_init(srslte_ue_ul_t *q,
srslte_cell_t cell)
srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -74,11 +74,9 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
if (srslte_harq_init(&q->harq_process[i], q->cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
goto clean_exit;
}
if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}
if (srslte_refsignal_ul_init(&q->dmrs, cell)) {
fprintf(stderr, "Error initiating srslte_refsignal_ul\n");
@ -113,9 +111,8 @@ void srslte_ue_ul_free(srslte_ue_ul_t *q) {
srslte_ofdm_rx_free(&q->fft);
srslte_pusch_free(&q->pusch);
srslte_pucch_free(&q->pucch);
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
srslte_harq_free(&q->harq_process[i]);
}
srslte_softbuffer_tx_free(&q->softbuffer);
srslte_cfo_free(&q->cfo);
srslte_refsignal_ul_free(&q->dmrs);
@ -154,14 +151,14 @@ void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q, uint16_t rnti) {
}
void srslte_ue_ul_reset(srslte_ue_ul_t *q) {
srslte_harq_reset(&q->harq_process[0]);
srslte_softbuffer_tx_reset(&q->softbuffer);
}
void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_pusch_hopping_cfg_t *pusch_hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg,
srslte_pucch_sched_t *pucch_sched)
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_pusch_hopping_cfg_t *pusch_hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg,
srslte_pucch_sched_t *pucch_sched)
{
srslte_refsignal_ul_set_pusch_cfg(&q->dmrs, dmrs_cfg);
srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg);
@ -274,11 +271,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
}
if (q->normalize_en) {
uint32_t n_prb = 1;
if (q->harq_process[0].ul_alloc.L_prb > 0) {
n_prb = q->harq_process[0].ul_alloc.L_prb;
}
float norm_factor = (float) q->cell.nof_prb/10/sqrtf(n_prb);
float norm_factor = (float) q->cell.nof_prb/10;
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
}
srslte_vec_save_file("pucch", output_signal, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
@ -288,64 +281,84 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
return ret;
}
int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, cf_t *output_signal)
int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, uint32_t sf_idx, uint32_t rv, cf_t *output_signal)
{
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return srslte_ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal);
return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv, q->current_rnti, output_signal);
}
int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, uint16_t rnti, cf_t *output_signal)
int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, uint32_t sf_idx, uint32_t rv, uint16_t rnti, cf_t *output_signal)
{
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return srslte_ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, rnti, output_signal);
return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv,rnti, output_signal);
}
int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, srslte_uci_data_t uci_data, uint32_t sf_idx, cf_t *output_signal)
int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, srslte_uci_data_t uci_data, uint32_t sf_idx, uint32_t rv, cf_t *output_signal)
{
return srslte_ue_ul_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal);
return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv, q->current_rnti, output_signal);
}
int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, srslte_uci_data_t uci_data,
uint32_t sf_idx, uint16_t rnti,
cf_t *output_signal)
int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant,
uint8_t *data, srslte_uci_data_t uci_data,
uint32_t sf_idx, uint32_t rv, uint16_t rnti,
cf_t *output_signal)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
ra_ul != NULL &&
grant != NULL &&
data != NULL &&
output_signal != NULL)
{
if (ra_ul->prb_alloc.L_prb == 0) {
if (grant->L_prb == 0) {
fprintf(stderr, "Invalid UL PRB allocation (L_prb=0)\n");
return ret;
}
ret = SRSLTE_ERROR;
if (srslte_harq_setup_ul(&q->harq_process[0], ra_ul->mcs, ra_ul->rv_idx, sf_idx, &ra_ul->prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return ret;
}
if (srslte_pusch_encode_rnti(&q->pusch, &q->harq_process[0], data, rnti, q->sf_symbols)) {
memcpy(&q->pusch_cfg.grant, grant, sizeof(srslte_ra_ul_grant_t));
q->pusch_cfg.sf_idx = sf_idx;
q->pusch_cfg.rv = rv;
q->pusch_cfg.cp = q->cell.cp;
srslte_cbsegm(&q->pusch_cfg.cb_segm, grant->mcs.tbs);
return srslte_ue_ul_pusch_encode_cfg(q, &q->pusch_cfg, data, uci_data, rnti, output_signal);
}
return ret;
}
int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg,
uint8_t *data, srslte_uci_data_t uci_data,
uint16_t rnti,
cf_t *output_signal)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
cfg != NULL &&
data != NULL &&
output_signal != NULL)
{
if (srslte_pusch_encode_rnti(&q->pusch, cfg, &q->softbuffer, data, rnti, q->sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
return ret;
}
// FIXME: Pregenerate for all possible number of prb
if (srslte_refsignal_dmrs_pusch_gen(&q->dmrs, q->harq_process[0].ul_alloc.L_prb, sf_idx, q->refsignal))
if (srslte_refsignal_dmrs_pusch_gen(&q->dmrs, cfg->grant.L_prb, cfg->sf_idx, q->refsignal))
{
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
return ret;
}
srslte_refsignal_dmrs_pusch_put(&q->dmrs, q->refsignal,
q->harq_process[0].ul_alloc.L_prb,
q->harq_process[0].ul_alloc.n_prb_tilde,
q->sf_symbols);
cfg->grant.L_prb,
cfg->grant.n_prb_tilde,
q->sf_symbols);
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
@ -354,7 +367,7 @@ int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_
}
if (q->normalize_en) {
float norm_factor = (float) q->cell.nof_prb/10/sqrtf(q->harq_process[0].ul_alloc.L_prb);
float norm_factor = (float) q->cell.nof_prb/10/sqrtf(cfg->grant.L_prb);
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
}

@ -81,7 +81,7 @@ bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_t
return ret;
}
bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant)
bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, ul_sched_grant *grant)
{
if (signal_buffer) {
if (!sf_symbols_and_ce_done) {
@ -102,19 +102,12 @@ bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant)
return false;
}
if (srslte_dci_msg_to_ra_ul(&dci_msg, cell.nof_prb,
params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET),
(srslte_ra_pusch_t*) grant->get_grant_ptr()))
{
return false;
}
return true;
return grant->create_from_dci(&dci_msg, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
}
}
bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant)
bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, dl_sched_grant *grant)
{
if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Getting DL grant\n", tti);
@ -145,18 +138,11 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant)
return false;
}
grant->set_ncce(srslte_ue_dl_get_ncce(&ue_dl));
if (srslte_dci_msg_to_ra_dl(&dci_msg, grant->get_rnti(), cell, cfi,
(srslte_ra_pdsch_t*) grant->get_grant_ptr())) {
return false;
}
return true;
return grant->create_from_dci(&dci_msg, cell, cfi, tti%10, srslte_ue_dl_get_ncce(&ue_dl));
}
}
bool dl_buffer::decode_ack(sched_grant pusch_grant)
bool dl_buffer::decode_ack(ul_sched_grant *grant)
{
if (signal_buffer && is_ready()) {
if (!sf_symbols_and_ce_done) {
@ -166,13 +152,11 @@ bool dl_buffer::decode_ack(sched_grant pusch_grant)
sf_symbols_and_ce_done = true;
}
srslte_ra_pusch_t *ra_ul = (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr();
return srslte_ue_dl_decode_phich(&ue_dl, tti%10, ra_ul->prb_alloc.n_prb[0], ra_ul->n_dmrs);
return srslte_ue_dl_decode_phich(&ue_dl, tti%10, grant->get_I_lowest(), grant->get_n_dmrs());
}
}
bool dl_buffer::decode_data(sched_grant pdsch_grant, uint8_t *payload)
bool dl_buffer::decode_data(dl_sched_grant *grant, uint8_t *payload)
{
if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Decoding PDSCH\n", tti);
@ -184,18 +168,13 @@ bool dl_buffer::decode_data(sched_grant pdsch_grant, uint8_t *payload)
sf_symbols_and_ce_done = true;
}
srslte_ra_pdsch_t *ra_dl = (srslte_ra_pdsch_t*) pdsch_grant.get_grant_ptr();
if (srslte_harq_setup_dl(&ue_dl.harq_process[0], ra_dl->mcs,
ra_dl->rv_idx, tti%10, &ra_dl->prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return SRSLTE_ERROR;
}
if (ue_dl.harq_process[0].mcs.mod > 0 && ue_dl.harq_process[0].mcs.tbs >= 0) {
int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.harq_process[0], ue_dl.sf_symbols,
ue_dl.ce, 0, pdsch_grant.get_rnti(), payload);
grant->get_pdsch_cfg(tti%10, &ue_dl.pdsch_cfg);
if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) {
int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, &ue_dl.softbuffer, ue_dl.sf_symbols,
ue_dl.ce, 0, grant->get_rnti(), payload);
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_vec_save_file((char*) "pdsch_d", ue_dl.pdsch.d, ue_dl.harq_process[0].nof_re*sizeof(cf_t));
srslte_vec_save_file((char*) "pdsch_d", ue_dl.pdsch.d, ue_dl.pdsch_cfg.grant.nof_re*sizeof(cf_t));
}
if (ret == SRSLTE_SUCCESS) {
return true;

@ -102,15 +102,10 @@ void phy::set_timeadv(uint32_t ta_cmd) {
INFO("Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6);
}
void phy::rar_ul_grant(uint32_t rba, uint32_t trunc_mcs, bool hopping_flag, sched_grant *grant)
void phy::rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant)
{
uint32_t n_ho = params_db.get_param(phy_params::PUSCH_HOPPING_OFFSET);
srslte_ra_pusch_t *ra_pusch = (srslte_ra_pusch_t*) grant->get_grant_ptr();
srslte_dci_rar_to_ra_ul(rba, trunc_mcs, hopping_flag, cell.nof_prb, ra_pusch);
srslte_ra_ul_alloc(&ra_pusch->prb_alloc, ra_pusch, n_ho, cell.nof_prb);
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, ra_pusch, cell.nof_prb);
}
grant->create_from_rar(rar, cell, 0, params_db.get_param(phy_params::PUSCH_HOPPING_OFFSET));
}
void phy::set_param(phy_params::phy_param_t param, int64_t value) {

@ -51,7 +51,7 @@ void prach::free_cell()
free(signal_buffer);
}
srslte_cfo_free(&cfo_h);
srslte_prach_free(&prach);
srslte_prach_free(&prach_obj);
}
}
@ -60,7 +60,7 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_)
cell = cell_;
params_db = params_db_;
preamble_idx = -1;
if (srslte_prach_init(&prach, srslte_symbol_sz(cell.nof_prb),
if (srslte_prach_init(&prach_obj, srslte_symbol_sz(cell.nof_prb),
srslte_prach_get_preamble_format(params_db->get_param(phy_params::PRACH_CONFIG_INDEX)),
params_db->get_param(phy_params::PRACH_ROOT_SEQ_IDX),
params_db->get_param(phy_params::PRACH_HIGH_SPEED_FLAG)?true:false,
@ -68,13 +68,13 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_)
return false;
}
len = prach.N_seq + prach.N_cp;
len = prach_obj.N_seq + prach_obj.N_cp;
for (uint32_t i=0;i<64;i++) {
buffer[i] = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t));
if(!buffer[i]) {
return false;
}
if(srslte_prach_gen(&prach, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])){
if(srslte_prach_gen(&prach_obj, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])){
return false;
}
}

@ -1,147 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \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 Lesser 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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 <strings.h>
#include <pthread.h>
#include "srslte/srslte.h"
#include "srslte/ue_itf/sched_grant.h"
namespace srslte {
namespace ue {
sched_grant::sched_grant(direction_t direction, uint16_t rnti_)
{
rnti = rnti_;
dir = direction;
}
/* Returns the RNTI associated with the UL/DL scheduling grant */
uint16_t sched_grant::get_rnti() {
return rnti;
}
uint32_t sched_grant::get_rv() {
if (dir == UPLINK) {
return ul_grant.rv_idx;
} else {
return dl_grant.rv_idx;
}
}
uint32_t sched_grant::get_tbs() {
if (dir == UPLINK) {
return ul_grant.mcs.tbs;
} else {
return dl_grant.mcs.tbs;
}
}
uint32_t sched_grant::get_ncce()
{
return ncce;
}
bool srslte::ue::sched_grant::is_sps_release()
{
return false;
}
void sched_grant::set_ncce(uint32_t ncce_)
{
ncce = ncce_;
}
uint32_t sched_grant::get_current_tx_nb()
{
return current_tx_nb;
}
void sched_grant::set_current_tx_nb(uint32_t current_tx_nb_)
{
current_tx_nb = current_tx_nb_;
}
void sched_grant::set_rv(uint32_t rv) {
if (dir == UPLINK) {
ul_grant.rv_idx = rv;
} else {
dl_grant.rv_idx = rv;
}
}
bool sched_grant::get_ndi() {
if (dir == UPLINK) {
return ul_grant.ndi;
} else {
return dl_grant.ndi;
}
}
void sched_grant::set_ndi(bool value) {
if (dir == UPLINK) {
ul_grant.ndi = value;
} else {
dl_grant.ndi = value;
}
}
bool sched_grant::get_cqi_request() {
if (dir == UPLINK) {
return ul_grant.ndi;
} else {
return dl_grant.ndi;
}
}
int sched_grant::get_harq_process() {
if (dir == UPLINK) {
return -1;
} else {
return dl_grant.harq_process;
}
}
bool sched_grant::is_uplink() {
return dir == UPLINK;
}
bool sched_grant::is_downlink() {
return dir == DOWNLINK;
}
void* sched_grant::get_grant_ptr() {
if (is_uplink()) {
return (void*) &ul_grant;
} else {
return (void*) &dl_grant;
}
}
} // namespace ue
} // namespace srslte

@ -63,12 +63,12 @@ void ul_buffer::free_cell() {
}
}
bool ul_buffer::generate_ack(bool ack, sched_grant last_dl_grant)
bool ul_buffer::generate_ack(bool ack, dl_sched_grant *last_dl_grant)
{
uci_data.uci_ack_len = 1;
uci_data.uci_ack = ack?1:0;
uci_pending = true;
last_n_cce = last_dl_grant.get_ncce();
last_n_cce = last_dl_grant->get_ncce();
}
bool ul_buffer::generate_ack(bool ack[2])
@ -89,11 +89,11 @@ bool ul_buffer::uci_ready() {
}
bool ul_buffer::generate_data() {
sched_grant dummy(sched_grant::DOWNLINK, 0);
return generate_data(dummy, NULL);
ul_sched_grant dummy(0);
return generate_data(&dummy, NULL);
}
bool ul_buffer::generate_data(sched_grant pusch_grant,
bool ul_buffer::generate_data(ul_sched_grant *grant,
uint8_t *payload)
{
if (is_ready()) {
@ -115,7 +115,7 @@ bool ul_buffer::generate_data(sched_grant pusch_grant,
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF :
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET);
pusch_hopping.current_tx_nb = pusch_grant.get_current_tx_nb();
pusch_hopping.current_tx_nb = grant->get_current_tx_nb();
srslte_pucch_cfg_t pucch_cfg;
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
@ -145,10 +145,12 @@ bool ul_buffer::generate_data(sched_grant pusch_grant,
int n = 0;
// Transmit on PUSCH if UL grant available, otherwise in PUCCH
if (payload) {
n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(),
payload, uci_data,
tti%10, pusch_grant.get_rnti(),
signal_buffer);
grant->to_pusch_cfg(tti%10, cell.cp, &pusch_cfg);
n = srslte_ue_ul_pusch_encode_cfg(&ue_ul, &pusch_cfg,
payload, uci_data,
grant->get_rnti(),
signal_buffer);
} else {
n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer);
}

@ -214,8 +214,9 @@ void config_phy() {
phy.set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_HOPPING_EN, 0);
phy.set_param(srslte::ue::phy_params::PUSCH_RS_SEQUENCE_HOPPING_EN, 0);
phy.set_param(srslte::ue::phy_params::PUSCH_RS_CYCLIC_SHIFT, 0);
phy.set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_ASSIGNMENT, 0);
phy.set_param(srslte::ue::phy_params::PUSCH_HOPPING_OFFSET, 0);
phy.set_param(srslte::ue::phy_params::PUCCH_BETA, 10);
phy.set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT, 1);
phy.set_param(srslte::ue::phy_params::PUCCH_CYCLIC_SHIFT, 0);
@ -253,7 +254,7 @@ void run_tti(uint32_t tti) {
}
}
if (state == RAR) {
srslte::ue::sched_grant rar_grant(srslte::ue::sched_grant::DOWNLINK, 2);
srslte::ue::dl_sched_grant rar_grant(2);
int ra_tti = phy.get_prach_transmitted_tti();
if (ra_tti > 0) {
INFO("PRACH was transmitted at %d\n", ra_tti);
@ -265,7 +266,7 @@ void run_tti(uint32_t tti) {
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant))
{
// Decode packet
if (dl_buffer->decode_data(rar_grant, payload)) {
if (dl_buffer->decode_data(&rar_grant, payload)) {
rar_unpack(payload, &rar_msg);
if (!prog_args.continous) {
printf("Received RAR for preamble %d\n", rar_msg.RAPID);
@ -283,8 +284,12 @@ void run_tti(uint32_t tti) {
phy.set_timeadv_rar(rar_msg.timing_adv_cmd);
// Generate Msg3 grant
srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti);
phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant);
srslte::ue::ul_sched_grant connreq_grant(rar_msg.temp_c_rnti);
srslte_dci_rar_grant_t rar_grant;
rar_grant.rba = rar_msg.rba;
rar_grant.trunc_mcs = rar_msg.mcs;
rar_grant.hopping_flag = rar_msg.hopping_flag;
phy.rar_ul_grant(&rar_grant, &connreq_grant);
// Pack Msg3 bits
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs());
@ -296,7 +301,7 @@ void run_tti(uint32_t tti) {
if (ul_buffer) {
connreq_grant.set_rv(0);
INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti);
//ul_buffer->generate_pusch(connreq_grant, payload);
ul_buffer->generate_data(&connreq_grant, payload);
// Save transmission time
conreq_tti = ul_buffer->tti;
@ -318,11 +323,15 @@ void run_tti(uint32_t tti) {
uint32_t interval_conreq = interval(tti, conreq_tti);
if (interval_conreq == 4) {
srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti);
phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant);
srslte::ue::ul_sched_grant connreq_grant(rar_msg.temp_c_rnti);
srslte_dci_rar_grant_t rar_grant;
rar_grant.rba = rar_msg.rba;
rar_grant.trunc_mcs = rar_msg.mcs;
rar_grant.hopping_flag = rar_msg.hopping_flag;
phy.rar_ul_grant(&rar_grant, &connreq_grant);
// Decode PHICH from Connection Request
if (!dl_buffer->decode_ack(connreq_grant)) {
if (!dl_buffer->decode_ack(&connreq_grant)) {
// Pack Msg3 bits
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs());
@ -339,7 +348,7 @@ void run_tti(uint32_t tti) {
connreq_grant.set_current_tx_nb(nof_rtx_connsetup);
connreq_grant.set_rv(rv_value[nof_rtx_connsetup%4]);
INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti);
ul_buffer->generate_data(connreq_grant, payload);
ul_buffer->generate_data(&connreq_grant, payload);
// Save transmission time
conreq_tti = ul_buffer->tti;
@ -354,13 +363,13 @@ void run_tti(uint32_t tti) {
}
}
if (state == CONNSETUP) {
srslte::ue::sched_grant conn_setup_grant(srslte::ue::sched_grant::DOWNLINK, rar_msg.temp_c_rnti);
srslte::ue::dl_sched_grant conn_setup_grant(rar_msg.temp_c_rnti);
bool connsetup_recv = false;
// Get DL grant for tmp_rnti
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant))
{
// Decode packet
if (dl_buffer->decode_data(conn_setup_grant, payload)) {
if (dl_buffer->decode_data(&conn_setup_grant, payload)) {
nof_rx_connsetup++;
state = RA;
nof_rtx_connsetup=0;
@ -375,7 +384,7 @@ void run_tti(uint32_t tti) {
// send ACK
INFO("Sending ack %d on TTI: %d\n", connsetup_recv, tti+4);
srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+4);
ul_buffer->generate_ack(connsetup_recv, conn_setup_grant);
ul_buffer->generate_ack(connsetup_recv, &conn_setup_grant);
if (!prog_args.continous) {
while(ul_buffer->uci_ready()) {
sleep(1);

@ -92,7 +92,7 @@ uint8_t payload[1024];
// This is the MAC implementation
void run_tti(uint32_t tti) {
srslte::ue::sched_grant grant = srslte::ue::sched_grant(srslte::ue::sched_grant::DOWNLINK, SRSLTE_SIRNTI);
srslte::ue::dl_sched_grant grant(SRSLTE_SIRNTI);
INFO("MAC running tti: %d\n", tti);
// SIB1 is scheduled in subframe #5 of even frames
@ -106,9 +106,9 @@ void run_tti(uint32_t tti) {
total_dci++;
// MAC sets RV
grant.set_rv(((uint32_t) ceilf((float)3*((phy.tti_to_SFN(tti)/2)%4)/2))%4);
// Decode packet
if (!buffer->decode_data(grant, payload)) {
if (!buffer->decode_data(&grant, payload)) {
total_errors++;
}
}
@ -141,6 +141,12 @@ int main(int argc, char *argv[])
// Give it time to create thread
sleep(1);
// Set default parameters
phy.set_param(srslte::ue::phy_params::PRACH_CONFIG_INDEX, 0);
phy.set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX, 0);
phy.set_param(srslte::ue::phy_params::PRACH_HIGH_SPEED_FLAG, 0);
phy.set_param(srslte::ue::phy_params::PRACH_ZC_CONFIG, 1);
// Set RX freq and gain
phy.get_radio()->set_rx_freq(prog_args.uhd_freq);
phy.get_radio()->set_rx_gain(prog_args.uhd_gain);

@ -209,12 +209,12 @@ int main(int argc, char **argv) {
srslte_modem_table_lte(&modulator, modulation, false);
srslte_tcod_t turbocoder;
srslte_tcod_init(&turbocoder, MAX_LONG_CB);
srslte_tcod_init(&turbocoder, SRSLTE_TCOD_MAX_LEN_CB);
srslte_dft_precoding_t dft_precod;
srslte_dft_precoding_init(&dft_precod, 12);
nbits = srslte_find_cb_index(sf_n_samples/8/srslte_mod_bits_x_symbol(modulation)/3 - 12);
nbits = srslte_cbsegm_cbindex(sf_n_samples/8/srslte_mod_bits_x_symbol(modulation)/3 - 12);
uint32_t ncoded_bits = sf_n_samples/8/srslte_mod_bits_x_symbol(modulation);
uint8_t *data = malloc(sizeof(uint8_t)*nbits);

@ -368,8 +368,8 @@ int main(int argc, char **argv) {
float rsrp=0.0, rsrq=0.0, snr=0.0;
bool decode_pdsch;
int pdcch_tx=0;
srslte_ra_pdsch_t old_ra_dl;
bzero(&old_ra_dl, sizeof(srslte_ra_pdsch_t));
srslte_ra_dl_dci_t old_ra_dl;
bzero(&old_ra_dl, sizeof(srslte_ra_dl_dci_t));
ue_sync.correct_cfo = prog_args.enable_cfo;
@ -418,8 +418,8 @@ int main(int argc, char **argv) {
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data_packed, srslte_ue_sync_get_sfidx(&ue_sync), SRSLTE_SIRNTI,
((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
}
if (memcmp(&ue_dl.ra_dl, &old_ra_dl, sizeof(srslte_ra_pdsch_t))) {
memcpy(&old_ra_dl, &ue_dl.ra_dl, sizeof(srslte_ra_pdsch_t));
if (memcmp(&ue_dl.ra_dl, &old_ra_dl, sizeof(srslte_ra_dl_dci_t))) {
memcpy(&old_ra_dl, &ue_dl.ra_dl, sizeof(srslte_ra_dl_dci_t));
fflush(stdout);printf("\nCFI:\t%d\n", ue_dl.cfi);
printf("Format: %s\n", srslte_dci_format_string(ue_dl.dci_format));
srslte_ra_pdsch_fprint(stdout, &old_ra_dl, cell.nof_prb);

Loading…
Cancel
Save