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 "cuhd_handler.hpp"
#include "srslte/cuhd/cuhd.h" #include "srslte/cuhd/cuhd.h"
#define METADATA_VERBOSE //#define METADATA_VERBOSE
//#define HIDE_MESSAGES //#define HIDE_MESSAGES

@ -1,7 +1,7 @@
enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1); enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1);
pdschConfig=struct('Modulation','QPSK','RV',0,'TxScheme','Port0'); 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; TBs=1:111:15000;
e_bits=10000; e_bits=10000;

@ -10,7 +10,7 @@ Npackets = 1;
SNR_values = linspace(15,20,4); SNR_values = linspace(15,20,4);
%% Choose RMC %% 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); waveform = sum(waveform,2);
if ~isempty(recordedSignal) if ~isempty(recordedSignal)
@ -51,7 +51,7 @@ cec.InterpType = 'linear'; % 2D interpolation type
cec.InterpWindow = 'Centered'; % Interpolation window type cec.InterpWindow = 'Centered'; % Interpolation window type
cec.InterpWinSize = 1; % Interpolation window size 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 = zeros(size(SNR_values));
decoded_srslte = zeros(size(SNR_values)); decoded_srslte = zeros(size(SNR_values));

@ -1,20 +1,14 @@
clear 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); 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; TBs=0:13:211;
% cqilen=[0, 8, 17]; cqilen=[0, 8, 17];
% mods={'QPSK','16QAM','64QAM'}; mods={'QPSK','16QAM','64QAM'};
% rvs=0; rvs=0;
% betas=0:3:11; betas=[2.0 2.5 6.25];
TBs=88;
cqilen=0;
mods={'QPSK'};
rvs=0;
betas=0;
for i=1:length(TBs) for i=1:length(TBs)
for m=1:length(mods) for m=1:length(mods)
@ -28,9 +22,9 @@ for i=1:length(TBs)
puschConfig.Modulation = mods{m}; puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r); puschConfig.RV = rvs(r);
puschConfig.BetaCQI = 2+betas(bcqi); puschConfig.BetaCQI = betas(bcqi);
puschConfig.BetaRI = 2+betas(bri); puschConfig.BetaRI = betas(bri);
puschConfig.BetaACK = 2+betas(back); puschConfig.BetaACK = betas(back);
if (betas(bri)>0) if (betas(bri)>0)
ri_bit=randi(2,1,1)-1; ri_bit=randi(2,1,1)-1;

@ -2,13 +2,13 @@ clear
ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1); ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',0,'Modulation','16QAM','RV',0,'Shortened',0); 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; TBs=0:13:222;
cqilen=0;%[0, 8, 17]; cqilen=[0, 8, 17];
mods={'QPSK','16QAM','64QAM'}; mods={'QPSK','16QAM','64QAM'};
rvs=0;%[0, 3]; rvs=[0, 3];
betas=0:3:11; betas=[2.0 2.5 6.25];
for i=1:length(TBs) for i=1:length(TBs)
@ -23,9 +23,9 @@ for i=1:length(TBs)
puschConfig.Modulation = mods{m}; puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r); puschConfig.RV = rvs(r);
puschConfig.BetaCQI = 2+betas(bcqi); puschConfig.BetaCQI = betas(bcqi);
puschConfig.BetaRI = 2+betas(bri); puschConfig.BetaRI = betas(bri);
puschConfig.BetaACK = 2+betas(back); puschConfig.BetaACK = betas(back);
if (betas(bri)>0) if (betas(bri)>0)
ri_bit=randi(2,1,1)-1; 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(lib)
ADD_SUBDIRECTORY(examples) ADD_SUBDIRECTORY(examples)
add_subdirectory(tutorial_examples) #add_subdirectory(tutorial_examples)

@ -74,9 +74,10 @@ srslte_pbch_t pbch;
srslte_pcfich_t pcfich; srslte_pcfich_t pcfich;
srslte_pdcch_t pdcch; srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch; 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_regs_t regs;
srslte_ra_pdsch_t ra_dl; srslte_ra_dl_dci_t ra_dl;
cf_t *sf_buffer = NULL, *output_buffer = NULL; cf_t *sf_buffer = NULL, *output_buffer = NULL;
@ -253,15 +254,15 @@ void base_init() {
srslte_pdsch_set_rnti(&pdsch, 1234); srslte_pdsch_set_rnti(&pdsch, 1234);
if (srslte_harq_init(&harq_process, cell)) { if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
fprintf(stderr, "Error initiating HARQ process\n"); fprintf(stderr, "Error initiating soft buffer\n");
exit(-1); exit(-1);
} }
} }
void base_free() { void base_free() {
srslte_harq_free(&harq_process); srslte_softbuffer_tx_free(&softbuffer);
srslte_pdsch_free(&pdsch); srslte_pdsch_free(&pdsch);
srslte_pdcch_free(&pdcch); srslte_pdcch_free(&pdcch);
srslte_regs_free(&regs); srslte_regs_free(&regs);
@ -315,7 +316,7 @@ uint32_t prbset_to_bitmask() {
int update_radl() { 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.harq_process = 0;
ra_dl.mcs_idx = mcs_idx; ra_dl.mcs_idx = mcs_idx;
ra_dl.ndi = 0; ra_dl.ndi = 0;
@ -323,13 +324,17 @@ int update_radl() {
ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0; ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask(); 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_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); 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; return 0;
} }
@ -403,7 +408,7 @@ void *net_thread_fnc(void *arg) {
do { do {
n = srslte_netsource_read(&net_source, &data_unpacked[rpm], DATA_BUFF_SZ-rpm); n = srslte_netsource_read(&net_source, &data_unpacked[rpm], DATA_BUFF_SZ-rpm);
if (n > 0) { if (n > 0) {
int nbytes = 1+(ra_dl.mcs.tbs-1)/8; int nbytes = 1+(pdsch_cfg.grant.mcs.tbs-1)/8;
rpm += n; rpm += n;
INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes); INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes);
wpm = 0; wpm = 0;
@ -537,13 +542,6 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error updating parameters from control port\n"); 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 */ /* Transmit PDCCH + PDSCH only when there is data to send */
if (sf_idx != 0 && sf_idx != 5) { if (sf_idx != 0 && sf_idx != 5) {
if (net_port > 0) { if (net_port > 0) {
@ -552,8 +550,8 @@ int main(int argc, char **argv) {
INFO("Transmitting packet\n",0); INFO("Transmitting packet\n",0);
} }
} else { } else {
INFO("SF: %d, Generating %d random bits\n", sf_idx, ra_dl.mcs.tbs); INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs.tbs);
for (i=0;i<ra_dl.mcs.tbs;i++) { for (i=0;i<pdsch_cfg.grant.mcs.tbs;i++) {
data[i] = rand()%2; data[i] = rand()%2;
} }
send_data = true; send_data = true;
@ -563,6 +561,12 @@ int main(int argc, char **argv) {
} }
if (send_data) { 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); 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); 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)) { 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); 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"); fprintf(stderr, "Error encoding PDSCH\n");
exit(-1); exit(-1);
} }
if (net_port > 0 && net_packet_ready) { if (net_port > 0 && net_packet_ready) {
if (null_file_sink) { if (null_file_sink) {
srslte_bit_unpack_vector(data, data_tmp, ra_dl.mcs.tbs); srslte_bit_unpack_vector(data, data_tmp, pdsch_cfg.grant.mcs.tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1+(ra_dl.mcs.tbs-1)/8) < 0) { 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"); fprintf(stderr, "Error sending data through UDP socket\n");
} }
} }
@ -598,7 +602,7 @@ int main(int argc, char **argv) {
} else { } else {
#ifndef DISABLE_UHD #ifndef DISABLE_UHD
// FIXME // 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)); 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); cuhd_send(uhd, output_buffer, sf_n_samples, true);
#endif #endif

@ -566,7 +566,7 @@ void *plot_thread_run(void *arg) {
while(1) { while(1) {
sem_wait(&plot_sem); 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++) { for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i])); tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i]));
if (isinf(tmp_plot[i])) { if (isinf(tmp_plot[i])) {

@ -295,7 +295,8 @@ int main(int argc, char **argv) {
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
uint32_t sfn_offset; uint32_t sfn_offset;
rar_msg_t rar_msg; 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; uint32_t rar_window_start = 0, rar_trials = 0, rar_window_stop = 0;
srslte_timestamp_t uhd_time; srslte_timestamp_t uhd_time;
srslte_timestamp_t next_tx_time; srslte_timestamp_t next_tx_time;
@ -489,15 +490,16 @@ int main(int argc, char **argv) {
rar_unpack(data_rx, &rar_msg); rar_unpack(data_rx, &rar_msg);
rar_msg_fprint(stdout, &rar_msg); rar_msg_fprint(stdout, &rar_msg);
srslte_dci_rar_grant_t rar_grant;
srslte_dci_rar_to_ra_ul(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, cell.nof_prb, &ra_pusch); 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_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_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); 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); 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); printf("Setting CFO: %f (%f)\n", cfo, cfo*15000);
srslte_ue_ul_set_cfo(&ue_ul, cfo); 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) { if (n < 0) {
fprintf(stderr, "Error encoding PUSCH\n"); fprintf(stderr, "Error encoding PUSCH\n");
exit(-1); 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_LTE_BANDS 29
#define SRSLTE_NOF_TC_CB_SIZES 188
typedef enum SRSLTE_API { typedef enum SRSLTE_API {
SRSLTE_PHICH_NORM = 0, SRSLTE_PHICH_NORM = 0,
SRSLTE_PHICH_EXT 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, SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old,
uint32_t ta); 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_cp_string(srslte_cp_t cp);
SRSLTE_API char *srslte_mod_string(srslte_mod_t mod); 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 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 float srslte_band_fd(uint32_t earfcn);
SRSLTE_API int srslte_band_get_fd_band(uint32_t band, 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 #define _TC_INTERL_H
#include "srslte/config.h" #include "srslte/config.h"
#include <stdint.h>
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint32_t *forward; uint32_t *forward;

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

@ -28,7 +28,9 @@
/****************************************************************************** /******************************************************************************
* File: dci.h * 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 * 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; uint32_t nof_bits;
} srslte_dci_msg_t; } 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 /* Converts a received PDSCH DL scheduling DCI message
* to ra structures ready to be passed to the harq setup function * 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, SRSLTE_API int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg,
uint16_t msg_rnti, uint16_t msg_rnti,
srslte_cell_t cell, srslte_cell_t cell,
uint32_t cfi, uint32_t cfi,
srslte_ra_pdsch_t *ra_dl); uint32_t sf_idx,
srslte_ra_dl_dci_t *dl_dci,
SRSLTE_API int srslte_dci_msg_to_ra_ul(srslte_dci_msg_t *msg, srslte_ra_dl_grant_t *grant);
uint32_t nof_prb,
uint32_t n_rb_ho, SRSLTE_API int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg,
srslte_ra_pusch_t *ra_ul); srslte_cell_t cell,
uint32_t N_srs,
SRSLTE_API int srslte_dci_rar_to_ra_ul(uint32_t rba, uint32_t n_rb_ho,
uint32_t trunc_mcs, srslte_ra_ul_dci_t *ul_dci,
bool hopping_flag, srslte_ra_ul_grant_t *grant);
uint32_t nof_prb,
srslte_ra_pusch_t *ra); 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); 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); srslte_dci_msg_type_t type);
// For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PUSCH_SCHED // 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, srslte_dci_msg_t *msg,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg, 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); uint32_t nof_prb);
// For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED // 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_msg_t *msg,
srslte_dci_format_t format, srslte_dci_format_t format,
uint32_t nof_prb, uint32_t nof_prb,
bool crc_is_crnti); bool crc_is_crnti);
SRSLTE_API int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, 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, uint32_t nof_prb,
bool crc_is_crnti); 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/dci.h"
#include "srslte/phch/regs.h" #include "srslte/phch/regs.h"
#include "srslte/phch/sch.h" #include "srslte/phch/sch.h"
#include "srslte/phch/harq.h" #include "srslte/phch/pdsch_cfg.h"
#define SRSLTE_PDSCH_MAX_TDEC_ITERS 5 #define SRSLTE_PDSCH_MAX_TDEC_ITERS 5
/* PDSCH object */ /* PDSCH object */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
@ -87,25 +86,29 @@ SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
uint16_t rnti); uint16_t rnti);
SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t *q, 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, uint8_t *data,
cf_t *sf_symbols[SRSLTE_MAX_PORTS]); cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, 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, uint8_t *data,
uint16_t rnti, uint16_t rnti,
cf_t *sf_symbols[SRSLTE_MAX_PORTS]); cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t *q, 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 *sf_symbols,
cf_t *ce[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate, float noise_estimate,
uint8_t *data); uint8_t *data);
SRSLTE_API int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, 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 *sf_symbols,
cf_t *ce[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate, 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/scrambling/scrambling.h"
#include "srslte/phch/regs.h" #include "srslte/phch/regs.h"
#include "srslte/phch/sch.h" #include "srslte/phch/sch.h"
#include "srslte/phch/harq.h" #include "srslte/phch/pusch_cfg.h"
#include "srslte/dft/dft_precoding.h" #include "srslte/dft/dft_precoding.h"
#define SRSLTE_PUSCH_MAX_TDEC_ITERS 5 #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); uint16_t rnti);
SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q, 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, uint8_t *data,
cf_t *sf_symbols); cf_t *sf_symbols);
SRSLTE_API int srslte_pusch_encode_rnti(srslte_pusch_t *q, 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, uint8_t *data,
uint16_t rnti, uint16_t rnti,
cf_t *sf_symbols); cf_t *sf_symbols);
SRSLTE_API int srslte_pusch_uci_encode(srslte_pusch_t *q, 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, uint8_t *data,
srslte_uci_data_t uci_data, srslte_uci_data_t uci_data,
cf_t *sf_symbols); cf_t *sf_symbols);
SRSLTE_API int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, 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, uint8_t *data,
srslte_uci_data_t uci_data, srslte_uci_data_t uci_data,
uint16_t rnti, uint16_t rnti,
cf_t *sf_symbols); cf_t *sf_symbols);
SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q, 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 *sf_symbols,
cf_t *ce, cf_t *ce,
float noise_estimate, 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 * File: ra.h
* *
* Description: Structures and utility functions for DL/UL resource allocation. * 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 * Reference: 3GPP TS 36.213 version 10.0.1 Release 10
*****************************************************************************/ *****************************************************************************/
@ -42,6 +43,10 @@
#include "srslte/config.h" #include "srslte/config.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
/**************************************************
* Common structures used for Resource Allocation
**************************************************/
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_mod_t mod; srslte_mod_t mod;
int tbs; int tbs;
@ -78,39 +83,72 @@ typedef struct SRSLTE_API {
} mode; } mode;
} srslte_ra_type2_t; } srslte_ra_type2_t;
typedef struct SRSLTE_API {
bool prb_idx[SRSLTE_MAX_PRB];
uint32_t nof_prb;
} srslte_ra_prb_slot_t;
/**************************************************
* Structures used for Downlink Resource Allocation
**************************************************/
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_ra_prb_slot_t slot[2]; bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t lstart; uint32_t lstart;
uint32_t re_sf[SRSLTE_NSUBFRAMES_X_FRAME]; uint32_t nof_re;
} srslte_ra_dl_alloc_t; 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 { 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;
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; srslte_ra_type_t alloc_type;
union { union {
srslte_ra_type0_t type0_alloc; srslte_ra_type0_t type0_alloc;
srslte_ra_type1_t type1_alloc; srslte_ra_type1_t type1_alloc;
srslte_ra_type2_t type2_alloc; srslte_ra_type2_t type2_alloc;
}; };
srslte_ra_dl_alloc_t prb_alloc;
uint32_t mcs_idx; uint32_t mcs_idx;
srslte_ra_mcs_t mcs;
uint32_t harq_process; uint32_t harq_process;
uint32_t rv_idx; uint32_t rv_idx;
bool ndi; 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 { 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. /* 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. * SRSLTE_RA_PUSCH_HOP_QUART is 00 for > 10 Mhz and SRSLTE_RA_PUSCH_HOP_QUART_NEG is 01 for > 10 Mhz.
@ -123,54 +161,46 @@ typedef struct SRSLTE_API {
SRSLTE_RA_PUSCH_HOP_TYPE2 = 3 SRSLTE_RA_PUSCH_HOP_TYPE2 = 3
} freq_hop_fl; } freq_hop_fl;
srslte_ra_ul_alloc_t prb_alloc; srslte_ra_ul_grant_t prb_alloc;
srslte_ra_type2_t type2_alloc; srslte_ra_type2_t type2_alloc;
uint32_t mcs_idx; uint32_t mcs_idx;
srslte_ra_mcs_t mcs; uint32_t rv_idx;
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 n_dmrs; uint32_t n_dmrs;
bool ndi; bool ndi;
bool cqi_request; 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, * Functions
uint32_t n_rb_ho, **************************************************/
uint32_t nof_prb);
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, SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t* dci,
uint32_t nof_prb); 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, SRSLTE_API void srslte_dl_dci_to_grant_nof_re(srslte_ra_dl_grant_t *grant,
uint32_t nof_prb); srslte_cell_t cell,
uint32_t sf_idx,
SRSLTE_API int srslte_ra_mcs_from_idx_dl(uint32_t mcs_idx, uint32_t nof_ctrl_symbols);
uint32_t nof_prb,
srslte_ra_mcs_t *mcs);
SRSLTE_API int srslte_ra_mcs_from_idx_ul(uint32_t mcs_idx, SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci,
uint32_t nof_prb, srslte_ra_ul_grant_t *grant,
srslte_ra_mcs_t *mcs); srslte_cell_t cell,
uint32_t n_rb_ho,
uint32_t N_srs);
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, SRSLTE_API int srslte_ra_tbs_from_idx(uint32_t tbs_idx,
uint32_t n_prb); 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 uint32_t srslte_ra_type1_N_rb(uint32_t nof_prb);
SRSLTE_API void srslte_ra_pdsch_fprint(FILE *f, SRSLTE_API void srslte_ra_pdsch_fprint(FILE *f,
srslte_ra_pdsch_t *ra, srslte_ra_dl_dci_t *ra,
uint32_t nof_prb); 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_API void srslte_ra_pusch_fprint(FILE *f,
srslte_ra_pusch_t *ra, srslte_ra_ul_dci_t *ra,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API void srslte_ra_ul_grant_fprint(FILE *f,
srslte_ra_ul_grant_t *grant);
#endif /* RB_ALLOC_H_ */ #endif /* RB_ALLOC_H_ */

@ -42,7 +42,8 @@
#include "srslte/fec/turbocoder.h" #include "srslte/fec/turbocoder.h"
#include "srslte/fec/turbodecoder.h" #include "srslte/fec/turbodecoder.h"
#include "srslte/fec/crc.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" #include "srslte/phch/uci.h"
#define SRSLTE_PDSCH_MAX_TDEC_ITERS 5 #define SRSLTE_PDSCH_MAX_TDEC_ITERS 5
@ -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 uint32_t srslte_sch_last_noi(srslte_sch_t *q);
SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q, SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q,
srslte_harq_t *harq_process, srslte_pdsch_cfg_t *cfg,
uint8_t *data, srslte_softbuffer_tx_t *softbuffer,
uint8_t *e_bits); uint8_t *data,
uint8_t *e_bits);
SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q, SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q,
srslte_harq_t *harq_process, srslte_pdsch_cfg_t *cfg,
float *e_bits, srslte_softbuffer_rx_t *softbuffer,
uint8_t *data); float *e_bits,
uint8_t *data);
SRSLTE_API int srslte_ulsch_encode(srslte_sch_t *q, SRSLTE_API int srslte_ulsch_encode(srslte_sch_t *q,
srslte_harq_t *harq_process, srslte_pusch_cfg_t *cfg,
uint8_t *data, srslte_softbuffer_tx_t *softbuffer,
uint8_t *g_bits, uint8_t *data,
uint8_t *q_bits); uint8_t *g_bits,
uint8_t *q_bits);
SRSLTE_API int srslte_ulsch_uci_encode(srslte_sch_t *q, SRSLTE_API int srslte_ulsch_uci_encode(srslte_sch_t *q,
srslte_harq_t *harq_process, srslte_pusch_cfg_t *cfg,
uint8_t *data, srslte_softbuffer_tx_t *softbuffer,
srslte_uci_data_t uci_data, uint8_t *data,
uint8_t *g_bits, srslte_uci_data_t uci_data,
uint8_t *q_bits); uint8_t *g_bits,
uint8_t *q_bits);
SRSLTE_API int srslte_ulsch_decode(srslte_sch_t *q, SRSLTE_API int srslte_ulsch_decode(srslte_sch_t *q,
srslte_harq_t *harq_process, srslte_pusch_cfg_t *cfg,
float *e_bits, srslte_softbuffer_rx_t *softbuffer,
uint8_t *data); 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 #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/config.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/phch/harq.h" #include "srslte/phch/pusch_cfg.h"
#include "srslte/fec/crc.h" #include "srslte/fec/crc.h"
#define SRSLTE_UCI_MAX_CQI_LEN_PUSCH 512 #define SRSLTE_UCI_MAX_CQI_LEN_PUSCH 512
#define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13 #define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13
#define SRSLTE_UCI_CQI_CODED_PUCCH_B 20 #define SRSLTE_UCI_CQI_CODED_PUCCH_B 20
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_crc_t crc; srslte_crc_t crc;
uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH]; 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 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_API int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q,
srslte_pusch_cfg_t *cfg,
uint8_t *cqi_data, uint8_t *cqi_data,
uint32_t cqi_len, uint32_t cqi_len,
float beta, float beta,
uint32_t Q_prime_ri, uint32_t Q_prime_ri,
srslte_harq_t *harq_process,
uint8_t *q_bits); uint8_t *q_bits);
SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data,
uint32_t cqi_len, uint32_t cqi_len,
uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]); uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]);
SRSLTE_API int srslte_uci_encode_ack(uint8_t data, SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint32_t O_cqi, uint32_t O_cqi,
float beta, float beta,
srslte_harq_t *harq_process,
uint32_t H_prime_total, uint32_t H_prime_total,
uint8_t *q_bits); uint8_t *q_bits);
SRSLTE_API int srslte_uci_encode_ri(uint8_t data, SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint32_t O_cqi, uint32_t O_cqi,
float beta, float beta,
srslte_harq_t *harq_process,
uint32_t H_prime_total, uint32_t H_prime_total,
uint8_t *q_bits); uint8_t *q_bits);

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

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

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

@ -63,8 +63,10 @@ typedef struct SRSLTE_API {
float current_cfo; float current_cfo;
srslte_pusch_cfg_t pusch_cfg;
srslte_refsignal_ul_t dmrs; 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_pusch_t pusch;
srslte_pucch_t pucch; 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); cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, 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, uint8_t *data,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rv,
cf_t *output_signal); cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q, 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, uint8_t *data,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rv,
uint16_t rnti, uint16_t rnti,
cf_t *output_signal); cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q, 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, uint8_t *data,
srslte_uci_data_t uci_data, srslte_uci_data_t uci_data,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rv,
cf_t *output_signal); cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, 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, uint8_t *data,
srslte_uci_data_t uci_data, srslte_uci_data_t uci_data,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rv,
uint16_t rnti, uint16_t rnti,
cf_t *output_signal); 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_reset(srslte_ue_ul_t *q);
SRSLTE_API void srslte_ue_ul_set_rnti(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/srslte.h"
#include "srslte/ue_itf/queue.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" #include "srslte/ue_itf/phy_params.h"
#ifndef UEDLBUFFER_H #ifndef UEDLBUFFER_H
@ -64,10 +65,11 @@ namespace ue {
bool init_cell(srslte_cell_t cell, phy_params *params_db); bool init_cell(srslte_cell_t cell, phy_params *params_db);
void free_cell(); void free_cell();
bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time); 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_ul_grant(pdcch_ul_search_t mode, ul_sched_grant *grant);
bool get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant); bool get_dl_grant(pdcch_dl_search_t mode, dl_sched_grant *grant);
bool decode_ack(srslte::ue::sched_grant pusch_grant); bool decode_ack(ul_sched_grant *pusch_grant);
bool decode_data(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO bool decode_data(dl_sched_grant *pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/NOK
private: private:
phy_params *params_db; phy_params *params_db;
srslte_cell_t cell; 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 class SRSLTE_API phy
{ {
public: public:
phy() {
started = false;
is_sfn_synched = false;
cell_is_set = false;
}
bool init(radio *radio_handler, tti_sync *ttisync); bool init(radio *radio_handler, tti_sync *ttisync);
void stop(); void stop();
@ -87,7 +91,7 @@ public:
void set_timeadv(uint32_t ta_cmd); void set_timeadv(uint32_t ta_cmd);
// Generate Msg3 UL grant from RAR // 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 // Get status
bool status_is_idle(); bool status_is_idle();
@ -114,8 +118,8 @@ private:
srslte_cell_t cell; srslte_cell_t cell;
bool cell_is_set; bool cell_is_set;
bool is_sfn_synched = false; bool is_sfn_synched;
bool started = false; bool started;
srslte_ue_sync_t ue_sync; srslte_ue_sync_t ue_sync;
srslte_ue_mib_t ue_mib; srslte_ue_mib_t ue_mib;

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

@ -37,34 +37,20 @@ namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */ /* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class SRSLTE_API sched_grant { class SRSLTE_API sched_grant {
public: public:
sched_grant(uint16_t rnti_) {
typedef enum {DOWNLINK=0, UPLINK=1} direction_t; rnti = rnti_;
sched_grant(direction_t direction, uint16_t rnti); }
uint16_t get_rnti(); uint16_t get_rnti() {
uint32_t get_rv(); return rnti;
void set_rv(uint32_t rv); }
bool get_ndi(); virtual uint32_t get_rv() = 0;
void set_ndi(bool value); virtual void set_rv(uint32_t rv) = 0;
bool get_cqi_request(); virtual bool get_ndi() = 0;
int get_harq_process(); virtual void set_ndi(bool value) = 0;
bool is_uplink(); virtual bool is_sps_release() = 0;
bool is_downlink(); virtual uint32_t get_tbs() = 0;
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);
protected: 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; uint16_t rnti;
uint32_t ncce;
}; };
} }

@ -28,7 +28,8 @@
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srslte/common/radio.h" #include "srslte/common/radio.h"
#include "srslte/ue_itf/queue.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" #include "srslte/ue_itf/phy_params.h"
#ifndef UEULBUFFER_H #ifndef UEULBUFFER_H
@ -48,26 +49,27 @@ namespace ue {
void free_cell(); void free_cell();
void set_tti(uint32_t tti); void set_tti(uint32_t tti);
void set_current_tx_nb(uint32_t current_tx_nb); 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_ack(bool ack[2]);
bool generate_sr(); bool generate_sr();
bool generate_cqi_report(); bool generate_cqi_report();
bool uci_ready(); bool uci_ready();
bool generate_data(); 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); 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 static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
private: private:
phy_params *params_db; phy_params *params_db;
srslte_cell_t cell; srslte_cell_t cell;
srslte_ue_ul_t ue_ul; srslte_ue_ul_t ue_ul;
bool cell_initiated; srslte_pusch_cfg_t pusch_cfg;
cf_t* signal_buffer; bool cell_initiated;
uint32_t current_tx_nb; cf_t* signal_buffer;
uint32_t last_n_cce; uint32_t current_tx_nb;
srslte_uci_data_t uci_data; uint32_t last_n_cce;
bool uci_pending; 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_chest_dl_t est;
srslte_precoding_t cheq; srslte_precoding_t cheq;
cf_t *input = NULL, *ce = NULL, *h = NULL, *output = NULL; 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 ret = -1;
int max_cid; int max_cid;
FILE *fmatlab = NULL; FILE *fmatlab = NULL;

@ -35,21 +35,6 @@
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/common/sequence.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 /* 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) { char *srslte_mod_string(srslte_mod_t mod) {
switch (mod) { switch (mod) {
case SRSLTE_MOD_BPSK: case SRSLTE_MOD_BPSK:
@ -219,21 +183,6 @@ uint32_t srslte_N_ta_new_rar(uint32_t ta) {
return ta*16; 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 srslte_sampling_freq_hz(uint32_t nof_prb) {
int n = srslte_symbol_sz(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/common/phy_common.h"
#include "srslte/fec/tc_interl.h" #include "srslte/fec/tc_interl.h"
#include "srslte/fec/turbocoder.h" #include "srslte/fec/turbocoder.h"
#include "srslte/fec/cbsegm.h"
#include "srslte/utils/debug.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; return -1;
} }
cb_table_idx = srslte_find_cb_index(long_cb); cb_table_idx = srslte_cbsegm_cbindex(long_cb);
if (cb_table_idx == -1) { if (cb_table_idx == -1) {
fprintf(stderr, "Can't find long_cb=%d in valid TC CB table\n", long_cb); fprintf(stderr, "Can't find long_cb=%d in valid TC CB table\n", long_cb);
return -1; return -1;

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

@ -152,7 +152,7 @@ int main(int argc, char **argv) {
if (test_known_data) { if (test_known_data) {
frame_length = KNOWN_DATA_LEN; frame_length = KNOWN_DATA_LEN;
} else { } 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; 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; 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"); mexErrMsgTxt("Invalid codeblock size\n");
return; return;
} }

@ -41,23 +41,25 @@
#include "srslte/utils/debug.h" #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, int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg, uint16_t msg_rnti,
srslte_cell_t cell, uint32_t cfi, srslte_cell_t cell, uint32_t cfi, uint32_t sf_idx,
srslte_ra_pdsch_t *ra_dl) srslte_ra_dl_dci_t *dl_dci,
srslte_ra_dl_grant_t *grant)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (msg != NULL && if (msg != NULL &&
ra_dl != NULL && grant != NULL &&
srslte_cell_isvalid(&cell) && srslte_cell_isvalid(&cell) &&
cfi > 0 && cfi > 0 &&
cfi < 4) cfi < 4)
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
srslte_dci_msg_type_t type; srslte_dci_msg_type_t type;
if (srslte_dci_msg_get_type(msg, &type, cell.nof_prb, msg_rnti)) { if (srslte_dci_msg_get_type(msg, &type, cell.nof_prb, msg_rnti)) {
fprintf(stderr, "Can't get DCI message type\n"); fprintf(stderr, "Can't get DCI message type\n");
return ret; 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); srslte_dci_msg_type_fprint(stdout, type);
} }
if (type.type == SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED) { 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; bool crc_is_crnti = false;
if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) { if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) {
crc_is_crnti = true; 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"); fprintf(stderr, "Can't unpack PDSCH message\n");
return ret; return ret;
} }
if (SRSLTE_VERBOSE_ISINFO()) { srslte_ra_dl_dci_to_grant(dl_dci, grant, cell, sf_idx, cfi, crc_is_crnti);
srslte_ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb);
}
if (srslte_ra_dl_alloc(&ra_dl->prb_alloc, ra_dl, cell.nof_prb)) { if (SRSLTE_VERBOSE_ISINFO()) {
fprintf(stderr, "Error computing resource allocation\n"); srslte_ra_pdsch_fprint(stdout, dl_dci, cell.nof_prb);
return ret; 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; ret = SRSLTE_SUCCESS;
} else { } else {
if (SRSLTE_VERBOSE_ISINFO()) { 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 /* 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) { int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar, srslte_cell_t cell,
bzero(ra, sizeof(srslte_ra_pusch_t)); uint32_t N_srs, uint32_t n_rb_ho,
if (!hopping_flag) { srslte_ra_ul_dci_t *ul_dci,
ra->freq_hop_fl = SRSLTE_RA_PUSCH_HOP_DISABLED; 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 { } else {
fprintf(stderr, "FIXME: Frequency hopping in RAR not implemented\n"); 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 // Truncate resource block assignment
uint32_t b = 0; uint32_t b = 0;
if (nof_prb <= 44) { if (cell.nof_prb <= 44) {
b = (uint32_t) (ceilf(log2((float) nof_prb*(nof_prb+1)/2))); b = (uint32_t) (ceilf(log2((float) cell.nof_prb*(cell.nof_prb+1)/2)));
riv = riv & ((1<<(b+1))-1); riv = riv & ((1<<(b+1))-1);
} }
ra->type2_alloc.riv = riv; ul_dci->type2_alloc.riv = riv;
ra->mcs_idx = trunc_mcs; ul_dci->mcs_idx = rar->trunc_mcs;
srslte_ra_type2_from_riv(riv, &ra->type2_alloc.L_crb, &ra->type2_alloc.RB_start, srslte_ra_type2_from_riv(riv, &ul_dci->type2_alloc.L_crb, &ul_dci->type2_alloc.RB_start,
nof_prb, nof_prb); 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; return SRSLTE_SUCCESS;
} }
/* Creates the UL PUSCH resource allocation grant from a DCI format 0 message /* 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (msg != NULL && if (msg != NULL &&
ra_ul != NULL) srslte_cell_isvalid(&cell) &&
grant != NULL)
{ {
ret = SRSLTE_ERROR; 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"); fprintf(stderr, "Can't unpack PDSCH message\n");
return ret; return ret;
} }
if (SRSLTE_VERBOSE_ISINFO()) { if (srslte_ra_ul_dci_to_grant(ul_dci, grant, cell, n_rb_ho, N_srs)) {
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)) {
fprintf(stderr, "Error computing resource allocation\n"); fprintf(stderr, "Error computing resource allocation\n");
return ret; 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; ret = SRSLTE_SUCCESS;
} }
return ret; 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 * 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 */ /* pack bits */
uint8_t *y = msg->data; 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 * 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 */ /* pack bits */
uint8_t *y = msg->data; 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 // CQI request
data->cqi_request = *y++ ? true : false; 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; 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 * 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 */ /* pack bits */
uint8_t *y = msg->data; 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; 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 */ /* pack bits */
uint8_t *y = msg->data; 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 */ /* unpack MCS according to 7.1.7 of 36.213 */
data->mcs_idx = srslte_bit_unpack(&y, 5); 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 */ /* harq process number */
data->harq_process = srslte_bit_unpack(&y, 3); data->harq_process = srslte_bit_unpack(&y, 3);
@ -511,6 +512,9 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_pdsch_t *data, uint32_t
// TPC not implemented // TPC not implemented
data->dci_format = SRSLTE_RA_DCI_FORMAT1;
return SRSLTE_SUCCESS; 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 * 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) { bool crc_is_crnti) {
/* pack bits */ /* 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 /* 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) { bool crc_is_crnti) {
/* pack bits */ /* 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 data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS
} }
uint32_t n_prb; data->dci_format = SRSLTE_RA_DCI_FORMAT1A;
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;
return SRSLTE_SUCCESS; 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 /* 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 */ /* pack bits */
uint8_t *y = msg->data; 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; 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; uint32_t L_p, RB_p;
/* pack bits */ /* 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->type2_alloc.riv = riv;
data->mcs_idx = srslte_bit_unpack(&y, 5); 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); msg->nof_bits = (y - msg->data);
return SRSLTE_SUCCESS; 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) { uint32_t nof_prb, bool crc_is_crnti) {
switch (format) { switch (format) {
case SRSLTE_DCI_FORMAT1: 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) { bool crc_is_crnti) {
if (msg->nof_bits == srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, nof_prb)) { if (msg->nof_bits == srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, nof_prb)) {
return dci_format1_unpack(msg, data, 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); 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); 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 "prb_dl.h"
#include "srslte/phch/pdsch.h" #include "srslte/phch/pdsch.h"
#include "srslte/phch/sch.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/utils/bit.h" #include "srslte/utils/bit.h"
#include "srslte/utils/debug.h" #include "srslte/utils/debug.h"
@ -58,7 +59,7 @@ extern int indices_ptr;
#endif #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 nsubframe, bool put) {
uint32_t s, n, l, lp, lstart, lend, nof_refs; uint32_t s, n, l, lp, lstart, lend, nof_refs;
bool is_pbch, is_sss; 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; uint32_t offset = 0;
INFO("%s %d RE from %d PRB\n", put ? "Putting" : "Getting", 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 #ifdef DEBUG_IDX
indices_ptr = 0; 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++) { for (n = 0; n < q->cell.nof_prb; n++) {
// If this PRB is assigned // If this PRB is assigned
if (prb_alloc->slot[s].prb_idx[n]) { if (grant->prb_idx[s][n]) {
if (s == 0) { if (s == 0) {
lstart = prb_alloc->lstart; lstart = grant->lstart;
} else { } else {
lstart = 0; 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 * 36.211 10.3 section 6.3.5
*/ */
int srslte_pdsch_put(srslte_pdsch_t *q, cf_t *symbols, cf_t *sf_symbols, 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) { srslte_ra_dl_grant_t *grant, uint32_t subframe) {
return srslte_pdsch_cp(q, symbols, sf_symbols, prb_alloc, subframe, true); 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 * 36.211 10.3 section 6.3.5
*/ */
int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols, 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) { srslte_ra_dl_grant_t *grant, uint32_t subframe) {
return srslte_pdsch_cp(q, sf_symbols, symbols, prb_alloc, subframe, false); return srslte_pdsch_cp(q, sf_symbols, symbols, grant, subframe, false);
} }
/** Initializes the PDCCH transmitter and receiver */ /** 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; 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 && if (q != NULL &&
sf_symbols != NULL && sf_symbols != NULL &&
data != NULL && data != NULL &&
harq != NULL) cfg != NULL)
{ {
if (q->rnti_is_set) { 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 { } else {
fprintf(stderr, "Must call srslte_pdsch_set_rnti() before calling srslte_pdsch_decode()\n"); fprintf(stderr, "Must call srslte_pdsch_set_rnti() before calling srslte_pdsch_decode()\n");
return SRSLTE_ERROR; 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 /** 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], int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
float noise_estimate, uint16_t rnti, uint8_t *data) 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 */ /* Set pointers for layermapping & precoding */
uint32_t i, n; uint32_t i, n;
cf_t *x[SRSLTE_MAX_LAYERS]; cf_t *x[SRSLTE_MAX_LAYERS];
if (q != NULL && if (q != NULL &&
sf_symbols != NULL && sf_symbols != NULL &&
data != NULL && data != NULL &&
harq != NULL) cfg != NULL)
{ {
INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", 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 */ /* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) { 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)); memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
/* extract symbols */ /* extract symbols */
n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &harq->dl_alloc, harq->sf_idx); n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &cfg->grant, cfg->sf_idx);
if (n != harq->nof_re) { if (n != cfg->grant.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
/* extract channel estimates */ /* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) { 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); n = srslte_pdsch_get(q, ce[i], q->ce[i], &cfg->grant, cfg->sf_idx);
if (n != harq->nof_re) { if (n != cfg->grant.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n);
return SRSLTE_ERROR; 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) { if (q->cell.nof_ports == 1) {
/* no need for layer demapping */ /* no need for layer demapping */
srslte_predecoding_single(&q->precoding, q->symbols[0], q->ce[0], q->d, 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 { } else {
srslte_predecoding_diversity(&q->precoding, q->symbols[0], q->ce, x, q->cell.nof_ports, 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, 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 /* 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 * 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_sigma_set(&q->demod, sqrt(0.5));
srslte_demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]); srslte_demod_soft_table_set(&q->demod, &q->mod[cfg->grant.mcs.mod]);
srslte_demod_soft_demodulate(&q->demod, q->d, q->e, harq->nof_re); srslte_demod_soft_demodulate(&q->demod, q->d, q->e, cfg->grant.nof_re);
/* descramble */ /* descramble */
if (rnti != q->rnti) { if (rnti != q->rnti) {
srslte_sequence_t seq; 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; 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); srslte_sequence_free(&seq);
} else { } 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 { } else {
return SRSLTE_ERROR_INVALID_INPUTS; 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 && if (q != NULL &&
data != NULL && data != NULL &&
harq != NULL) cfg != NULL)
{ {
if (q->rnti_is_set) { 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 { } else {
fprintf(stderr, "Must call srslte_pdsch_set_rnti() to set the encoder/decoder RNTI\n"); fprintf(stderr, "Must call srslte_pdsch_set_rnti() to set the encoder/decoder RNTI\n");
return SRSLTE_ERROR; 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 /** 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; int i;
/* Set pointers for layermapping & precoding */ /* 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 && if (q != NULL &&
data != NULL && data != NULL &&
harq != NULL) cfg != NULL)
{ {
for (i=0;i<q->cell.nof_ports;i++) { 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; return SRSLTE_ERROR_INVALID_INPUTS;
} }
if (harq->mcs.tbs > harq->nof_bits) { if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->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; return SRSLTE_ERROR_INVALID_INPUTS;
} }
if (harq->nof_re > q->max_re) { if (cfg->grant.nof_re > q->max_re) {
fprintf(stderr, fprintf(stderr,
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", "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; return SRSLTE_ERROR_INVALID_INPUTS;
} }
INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", 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 */ /* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) { 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)); 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"); fprintf(stderr, "Error encoding TB\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (rnti != q->rnti) { if (rnti != q->rnti) {
srslte_sequence_t seq; 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; 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); srslte_sequence_free(&seq);
} else { } 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 */ /* TODO: only diversity supported */
if (q->cell.nof_ports > 1) { 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, 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 { } 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 */ /* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) { 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; ret = SRSLTE_SUCCESS;
} }

@ -35,6 +35,7 @@
#include <math.h> #include <math.h>
#include "srslte/phch/pusch.h" #include "srslte/phch/pusch.h"
#include "srslte/phch/pusch_cfg.h"
#include "srslte/phch/uci.h" #include "srslte/phch/uci.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/utils/bit.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 *in_ptr = input;
cf_t *out_ptr = output; 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)) { if (SRSLTE_CP_ISEXT(q->cell.cp)) {
L_ref = 2; 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++) { for (uint32_t slot=0;slot<2;slot++) {
uint32_t n_prb_tilde = harq->ul_alloc.n_prb[slot]; uint32_t n_prb_tilde = grant->n_prb[slot];
if (harq->ul_alloc.freq_hopping == 1) { if (grant->freq_hopping == 1) {
if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) { 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 { } 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 */ /* 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) { if (hopping->n_sb > 1) {
n_vrb_tilde -= (hopping->hopping_offset-1)/2+1; n_vrb_tilde -= (hopping->hopping_offset-1)/2+1;
} }
int i=0; int i=0;
if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) { if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) {
i = harq->sf_idx; i = sf_idx;
} else { } else {
i = 2*harq->sf_idx+slot; i = 2*sf_idx+slot;
} }
uint32_t n_rb_sb = q->cell.nof_prb; uint32_t n_rb_sb = q->cell.nof_prb;
if (hopping->n_sb > 1) { 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; grant->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); 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++) { for (uint32_t l=0;l<SRSLTE_CP_NSYMB(q->cell.cp);l++) {
if (l != L_ref) { if (l != L_ref) {
uint32_t idx = SRSLTE_RE_IDX(q->cell.nof_prb, l+slot*SRSLTE_CP_NSYMB(q->cell.cp), 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 { } else {
in_ptr = &input[idx]; 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) { if (advance_input) {
in_ptr += harq->ul_alloc.L_prb*SRSLTE_NRE; in_ptr += grant->L_prb*SRSLTE_NRE;
} else { } 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) { 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, harq, input, output, true); 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) { 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, harq, input, output, false); 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 /** 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; uint32_t n;
if (q != NULL && if (q != NULL &&
sf_symbols != NULL && sf_symbols != NULL &&
data != NULL && data != NULL &&
harq != NULL) cfg != NULL)
{ {
if (q->rnti_is_set) { if (q->rnti_is_set) {
INFO("Decoding PUSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", 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 */ /* extract symbols */
n = get(q, harq, sf_symbols, q->d); n = pusch_get(q, &cfg->grant, cfg->sf_idx, sf_symbols, q->d);
if (n != harq->nof_re) { if (n != cfg->grant.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
/* extract channel estimates */ /* extract channel estimates */
n = get(q, harq, ce, q->ce); n = pusch_get(q, &cfg->grant, cfg->sf_idx, ce, q->ce);
if (n != harq->nof_re) { if (n != cfg->grant.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->grant.nof_re, n);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_predecoding_single(&q->equalizer, q->d, q->ce, q->z, 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, srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->grant.nof_symb);
harq->ul_alloc.L_prb, harq->nof_symb);
/* demodulate symbols /* demodulate symbols
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * 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 * 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_sigma_set(&q->demod, sqrt(0.5));
srslte_demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]); srslte_demod_soft_table_set(&q->demod, &q->mod[cfg->grant.mcs.mod]);
srslte_demod_soft_demodulate(&q->demod, q->d, q->q, harq->nof_re); srslte_demod_soft_demodulate(&q->demod, q->d, q->q, cfg->grant.nof_re);
/* descramble */ /* 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 { } else {
fprintf(stderr, "Must call srslte_pusch_set_rnti() before calling srslte_pusch_decode()\n"); fprintf(stderr, "Must call srslte_pusch_set_rnti() before calling srslte_pusch_decode()\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -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; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); 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) { if (q->rnti_is_set) {
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); 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 { } else {
fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n"); fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n");
return SRSLTE_ERROR; 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) { 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 { } else {
fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n"); fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n");
return SRSLTE_ERROR; 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 /** 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
data != NULL && data != NULL &&
harq != NULL) cfg != NULL)
{ {
if (harq->mcs.tbs > harq->nof_bits) { if (cfg->grant.mcs.tbs > cfg->grant.nof_bits) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits); fprintf(stderr, "Invalid code rate %.2f\n", (float) cfg->grant.mcs.tbs / cfg->grant.nof_bits);
return SRSLTE_ERROR_INVALID_INPUTS; 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", 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; return SRSLTE_ERROR_INVALID_INPUTS;
} }
INFO("Encoding PUSCH SF: %d, Mod %s, RNTI: %d, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", 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); bzero(q->q, cfg->grant.nof_bits);
if (srslte_ulsch_uci_encode(&q->dl_sch, harq, data, uci_data, q->g, q->q)) { if (srslte_ulsch_uci_encode(&q->dl_sch, cfg, softbuffer, data, uci_data, q->g, q->q)) {
fprintf(stderr, "Error encoding TB\n"); fprintf(stderr, "Error encoding TB\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (rnti != q->rnti) { if (rnti != q->rnti) {
srslte_sequence_t seq; 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; 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); srslte_sequence_free(&seq);
} else { } 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, srslte_dft_precoding(&q->dft_precoding, q->d, q->z, cfg->grant.L_prb, cfg->grant.nof_symb);
harq->ul_alloc.L_prb, harq->nof_symb);
/* mapping to resource elements */ /* 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; 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; return re;
} }
void srslte_ra_prb_fprint(FILE *f, srslte_ra_prb_slot_t *prb, uint32_t nof_prb) { int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant,
int i; uint32_t n_rb_ho, uint32_t nof_prb) {
if (prb->nof_prb > 0) { bzero(grant, sizeof(srslte_ra_ul_grant_t));
for (i=0;i<nof_prb;i++) { grant->L_prb = dci->type2_alloc.L_crb;
if (prb->prb_idx[i]) { uint32_t n_prb_1 = dci->type2_alloc.RB_start;
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;
uint32_t n_rb_pusch = 0; uint32_t n_rb_pusch = 0;
if (n_rb_ho%2) { if (n_rb_ho%2) {
n_rb_ho++; 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 /* For no freq hopping or type2 freq hopping, n_prb is the same
* n_prb_tilde is calculated during resource mapping * n_prb_tilde is calculated during resource mapping
*/ */
for (uint32_t i=0;i<2;i++) { 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) { if (dci->freq_hop_fl == SRSLTE_RA_PUSCH_HOP_DISABLED) {
prb_dist->freq_hopping = 0; grant->freq_hopping = 0;
} else { } 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 { } else {
/* Type1 frequency hopping as defined in 8.4.1 of 36.213 /* Type1 frequency hopping as defined in 8.4.1 of 36.213
* frequency offset between 1st and 2nd slot is fixed. * 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); n_rb_pusch = nof_prb - n_rb_ho - (nof_prb%2);
// starting prb idx for slot 0 is as given by resource grant // 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) { 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); 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; uint32_t n_prb_1_tilde = n_prb_1;
// prb idx for slot 1 // prb idx for slot 1
switch(ra->freq_hop_fl) { switch(dci->freq_hop_fl) {
case SRSLTE_RA_PUSCH_HOP_QUART: 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; break;
case SRSLTE_RA_PUSCH_HOP_QUART_NEG: case SRSLTE_RA_PUSCH_HOP_QUART_NEG:
if (n_prb_1 < n_rb_pusch/4) { 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 { } 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; break;
case SRSLTE_RA_PUSCH_HOP_HALF: 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; break;
default: default:
break; 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); 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);
prb_dist->freq_hopping = 1; 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; return SRSLTE_SUCCESS;
} }
/* Computes the number of RE for each PRB in the prb_dist structure */ /* 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, void srslte_dl_dci_to_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell,
uint32_t nof_ctrl_symbols, srslte_cp_t cp) { uint32_t sf_idx, uint32_t nof_ctrl_symbols)
uint32_t i, j, s; {
uint32_t 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 PRB
// Compute number of RE per subframe grant->nof_re = 0;
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { for (s = 0; s < 2; s++) {
prb_dist->re_sf[i] = 0; for (j = 0; j < cell.nof_prb; j++) {
for (s = 0; s < 2; s++) { if (grant->prb_idx[s][j]) {
for (j = 0; j < nof_prb; j++) { grant->nof_re += ra_re_x_prb(sf_idx, s, j,
if (prb_dist->slot[s].prb_idx[j]) { cell.nof_prb, cell.nof_ports, nof_ctrl_symbols, cell.cp);
prb_dist->re_sf[i] += ra_re_x_prb(i, s, j,
nof_prb, nof_ports, nof_ctrl_symbols, cp);
}
} }
} }
} }
} }
/** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */ /** 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; int i, j;
uint32_t bitmask; uint32_t bitmask;
uint32_t P = srslte_ra_type0_P(nof_prb); uint32_t P = srslte_ra_type0_P(nof_prb);
uint32_t n_rb_rbg_subset, n_rb_type1; uint32_t n_rb_rbg_subset, n_rb_type1;
bzero(prb_dist, sizeof(srslte_ra_dl_alloc_t)); bzero(grant, sizeof(srslte_ra_dl_grant_t));
switch (ra->alloc_type) { switch (dci->alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0: 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); int nb = (int) ceilf((float) nof_prb / P);
for (i = 0; i < nb; i++) { for (i = 0; i < nb; i++) {
if (bitmask & (1 << (nb - i - 1))) { if (bitmask & (1 << (nb - i - 1))) {
for (j = 0; j < P; j++) { for (j = 0; j < P; j++) {
if (i*P+j < nof_prb) { if (i*P+j < nof_prb) {
prb_dist->slot[0].prb_idx[i * P + j] = true; grant->prb_idx[0][i * P + j] = true;
prb_dist->slot[0].nof_prb++; 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; break;
case SRSLTE_RA_ALLOC_TYPE1: case SRSLTE_RA_ALLOC_TYPE1:
n_rb_type1 = srslte_ra_type1_N_rb(nof_prb); 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; 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; n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P + ((nof_prb - 1) % P) + 1;
} else { } else {
n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P; n_rb_rbg_subset = ((nof_prb - 1) / (P * P)) * P;
} }
int shift = ra->type1_alloc.shift ? (n_rb_rbg_subset - n_rb_type1) : 0; int shift = dci->type1_alloc.shift ? (n_rb_rbg_subset - n_rb_type1) : 0;
bitmask = ra->type1_alloc.vrb_bitmask; bitmask = dci->type1_alloc.vrb_bitmask;
for (i = 0; i < n_rb_type1; i++) { for (i = 0; i < n_rb_type1; i++) {
if (bitmask & (1 << (n_rb_type1 - i - 1))) { if (bitmask & (1 << (n_rb_type1 - i - 1))) {
prb_dist->slot[0].prb_idx[((i + shift) / P) grant->prb_idx[0][((i + shift) / P)
* P * P + ra->type1_alloc.rbg_subset * P + (i + shift) % P] = true; * P * P + dci->type1_alloc.rbg_subset * P + (i + shift) % P] = true;
prb_dist->slot[0].nof_prb++; 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; break;
case SRSLTE_RA_ALLOC_TYPE2: case SRSLTE_RA_ALLOC_TYPE2:
if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
for (i = 0; i < ra->type2_alloc.L_crb; i++) { for (i = 0; i < dci->type2_alloc.L_crb; i++) {
prb_dist->slot[0].prb_idx[i + ra->type2_alloc.RB_start] = true; grant->prb_idx[0][i + dci->type2_alloc.RB_start] = true;
prb_dist->slot[0].nof_prb++; 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 { } else {
/* Mapping of Virtual to Physical RB for distributed type is defined in /* Mapping of Virtual to Physical RB for distributed type is defined in
* 6.2.3.2 of 36.211 * 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, int N_gap, N_tilde_vrb, n_tilde_vrb, n_tilde_prb, n_tilde2_prb, N_null,
N_row, n_vrb; N_row, n_vrb;
int n_tilde_prb_odd, n_tilde_prb_even; 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_tilde_vrb = srslte_ra_type2_n_vrb_dl(nof_prb, true);
N_gap = srslte_ra_type2_ngap(nof_prb, true); N_gap = srslte_ra_type2_ngap(nof_prb, true);
} else { } 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_row = (int) ceilf((float) N_tilde_vrb / (4 * P)) * P;
N_null = 4 * N_row - N_tilde_vrb; N_null = 4 * N_row - N_tilde_vrb;
for (i = 0; i < ra->type2_alloc.L_crb; i++) { for (i = 0; i < dci->type2_alloc.L_crb; i++) {
n_vrb = i + ra->type2_alloc.RB_start; n_vrb = i + dci->type2_alloc.RB_start;
n_tilde_vrb = n_vrb % N_tilde_vrb; n_tilde_vrb = n_vrb % N_tilde_vrb;
n_tilde_prb = 2 * N_row * (n_tilde_vrb % 2) + n_tilde_vrb / 2 n_tilde_prb = 2 * N_row * (n_tilde_vrb % 2) + n_tilde_vrb / 2
+ N_tilde_vrb * (n_vrb / N_tilde_vrb); + 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); + N_tilde_vrb * (n_vrb / N_tilde_vrb);
if (n_tilde_prb_odd < N_tilde_vrb / 2) { 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 { } 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; - N_tilde_vrb / 2] = true;
} }
prb_dist->slot[0].nof_prb++; grant->nof_prb++;
if (n_tilde_prb_even < N_tilde_vrb / 2) { 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 { } 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; - N_tilde_vrb / 2] = true;
} }
prb_dist->slot[1].nof_prb++;
} }
} }
break; 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; return SRSLTE_SUCCESS;
} }
/* Returns the number of allocated PRB for Uplink */ /* Modulation order and transport block size determination 7.1.7 in 36.213 */
uint32_t srslte_ra_nprb_ul(srslte_ra_pusch_t *ra, uint32_t nof_prb) { static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, bool crc_is_crnti) {
return ra->type2_alloc.L_crb; 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 */ /** Obtains a DL grant from a DCI grant for PDSCH */
uint32_t srslte_ra_nprb_dl(srslte_ra_pdsch_t *ra, uint32_t nof_prb) { 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 nprb; uint32_t sf_idx, uint32_t cfi, bool crc_is_crnti)
uint32_t nof_rbg, P; {
switch (ra->alloc_type) { // Compute PRB allocation
case SRSLTE_RA_ALLOC_TYPE0: if (!dl_dci_to_grant_prb_allocation(dci, grant, cell.nof_prb)) {
// Get the number of allocated RBG except the last RBG // Compute number of RE
nof_rbg = srslte_bit_count(ra->type0_alloc.rbg_bitmask & 0xFFFFFFFE); srslte_dl_dci_to_grant_nof_re(grant, cell, sf_idx, cell.nof_prb<10?(cfi+1):cfi);
P = srslte_ra_type0_P(nof_prb); // Compute MCS
if (nof_rbg > (uint32_t) ceilf((float) nof_prb / P)) { if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) {
nof_rbg = (uint32_t) ceilf((float) nof_prb / P) - 1; // Fill rest of grant structure
} grant->lstart = cell.nof_prb<10?(cfi+1):cfi;
nprb = nof_rbg * P; grant->nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-grant->lstart;
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
// last RBG may have smaller size. Add if set grant->nof_bits = grant->nof_re * grant->Qm;
uint32_t P_last = (nof_prb % P); } else {
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; return SRSLTE_ERROR;
} }
break; } else {
case SRSLTE_RA_ALLOC_TYPE2:
nprb = ra->type2_alloc.L_crb;
break;
default:
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
return nprb; return SRSLTE_SUCCESS;
} }
/* RBG size for type0 scheduling as in table 7.1.6.1-1 of 36.213 */ /* 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 */ /* Table 7.1.7.2.1-1: Transport block size table 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 */
int srslte_ra_tbs_from_idx(uint32_t tbs_idx, uint32_t n_prb) { 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) { if (tbs_idx < 27 && n_prb > 0 && n_prb <= SRSLTE_MAX_PRB) {
return tbs_table[tbs_idx][n_prb - 1]; 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; 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", 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"); 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"); fprintf(f, "No\n");
} else { } else {
fprintf(f, "Yes\n"); fprintf(f, "Yes\n");
} }
fprintf(f, " + Resource Indicator Value:\t\t%d\n", ra->type2_alloc.riv); fprintf(f, " + Resource Indicator Value:\t\t%d\n", dci->type2_alloc.riv);
if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", 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 { } else {
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", 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", 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", 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", dci->mcs_idx);
fprintf(f, " - Modulation and coding scheme index:\t%d\n", ra->mcs_idx); fprintf(f, " - New data indicator:\t\t\t%s\n", dci->ndi ? "Yes" : "No");
fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(ra->mcs.mod)); fprintf(f, " - Redundancy version:\t\t\t%d\n", dci->rv_idx);
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, " - TPC command for PUCCH:\t\t--\n"); 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) { char *ra_type_string(srslte_ra_type_t alloc_type) {
switch (alloc_type) { switch (alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0: 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_dl_dci_t *dci, uint32_t nof_prb) {
void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_pdsch_t *ra, uint32_t nof_prb) {
fprintf(f, " - Resource Allocation Type:\t\t%s\n", fprintf(f, " - Resource Allocation Type:\t\t%s\n",
ra_type_string(ra->alloc_type)); ra_type_string(dci->alloc_type));
switch (ra->alloc_type) { switch (dci->alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0: case SRSLTE_RA_ALLOC_TYPE0:
fprintf(f, " + Resource Block Group Size:\t\t%d\n", srslte_ra_type0_P(nof_prb)); 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; break;
case SRSLTE_RA_ALLOC_TYPE1: case SRSLTE_RA_ALLOC_TYPE1:
fprintf(f, " + Resource Block Group Size:\t\t%d\n", srslte_ra_type0_P(nof_prb)); 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 Bitmap:\t\t\t0x%x\n", dci->type1_alloc.vrb_bitmask);
fprintf(f, " + RBG Subset:\t\t\t%d\n", ra->type1_alloc.rbg_subset); fprintf(f, " + RBG Subset:\t\t\t%d\n", dci->type1_alloc.rbg_subset);
fprintf(f, " + RBG Shift:\t\t\t\t%s\n", fprintf(f, " + RBG Shift:\t\t\t\t%s\n",
ra->type1_alloc.shift ? "Yes" : "No"); dci->type1_alloc.shift ? "Yes" : "No");
break; break;
case SRSLTE_RA_ALLOC_TYPE2: case SRSLTE_RA_ALLOC_TYPE2:
fprintf(f, " + Type:\t\t\t\t%s\n", fprintf(f, " + Type:\t\t\t\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, " + Resource Indicator Value:\t\t%d\n", ra->type2_alloc.riv); fprintf(f, " + Resource Indicator Value:\t\t%d\n", dci->type2_alloc.riv);
if (ra->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", 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 { } else {
fprintf(f, " + VRB Assignment:\t\t\t%d VRB starting with VRB %d\n", 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", 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", 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; 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");
}
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);
}
srslte_ra_dl_alloc_t alloc; void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
srslte_ra_dl_alloc(&alloc, ra, nof_prb); if (grant->nof_prb > 0) {
for (int s = 0; s < 2; s++) { for (int j=0;j<2;j++) {
fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", s); fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", j);
srslte_ra_prb_fprint(f, &alloc.slot[s], nof_prb); for (int i=0;i<SRSLTE_MAX_PRB;i++) {
if (grant->prb_idx[j][i]) {
fprintf(f, "%d, ", i);
}
}
fprintf(f, "\n");
}
} }
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");
} }

@ -34,6 +34,7 @@
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include "srslte/phch/pdsch.h"
#include "srslte/phch/pusch.h" #include "srslte/phch/pusch.h"
#include "srslte/phch/sch.h" #include "srslte/phch/sch.h"
#include "srslte/phch/uci.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}; 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 srslte_sch_init(srslte_sch_t *q) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q) { if (q) {
@ -69,22 +97,22 @@ int srslte_sch_init(srslte_sch_t *q) {
goto clean; 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"); fprintf(stderr, "Error initiating Turbo Coder\n");
goto clean; 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"); fprintf(stderr, "Error initiating Turbo Decoder\n");
goto clean; goto clean;
} }
// Allocate floats for reception (LLRs) // 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) { if (!q->cb_in) {
goto clean; 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) { if (!q->cb_out) {
goto clean; 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 /* 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 parity[24];
uint8_t *p_parity = parity; 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 i;
uint32_t cb_len, rp, wp, rlen, F, n_e; uint32_t cb_len, rp, wp, rlen, F, n_e;
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t Qm = srslte_mod_bits_x_symbol(harq->mcs.mod);
if (q != NULL && if (q != NULL &&
data != NULL && data != NULL &&
harq != NULL) e_bits != NULL &&
cb_segm != NULL &&
soft_buffer != NULL)
{ {
uint32_t Gp = nof_e_bits / Qm; uint32_t Gp = nof_e_bits / Qm;
uint32_t gamma = Gp; uint32_t gamma = Gp;
if (harq->cb_segm.C > 0) { if (cb_segm->C > 0) {
gamma = Gp%harq->cb_segm.C; gamma = Gp%cb_segm->C;
} }
if (harq->rv == 0) { if (rv == 0) {
/* Compute transport block CRC */ /* 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 */ /* parity bits will be appended later */
srslte_bit_pack(par, &p_parity, 24); srslte_bit_pack(par, &p_parity, 24);
if (SRSLTE_VERBOSE_ISDEBUG()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("DATA: ", 0); DEBUG("DATA: ", 0);
srslte_vec_fprint_b(stdout, data, harq->mcs.tbs); srslte_vec_fprint_b(stdout, data, cb_segm->tbs);
DEBUG("PARITY: ", 0); DEBUG("PARITY: ", 0);
srslte_vec_fprint_b(stdout, parity, 24); 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; wp = 0;
rp = 0; rp = 0;
for (i = 0; i < harq->cb_segm.C; i++) { for (i = 0; i < cb_segm->C; i++) {
/* Get read lengths */ /* Get read lengths */
if (i < harq->cb_segm.C2) { if (i < cb_segm->C2) {
cb_len = harq->cb_segm.K2; cb_len = cb_segm->K2;
} else { } 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; rlen = cb_len - 24;
} else { } else {
rlen = cb_len; rlen = cb_len;
} }
if (i == 0) { if (i == 0) {
F = harq->cb_segm.F; F = cb_segm->F;
} else { } else {
F = 0; F = 0;
} }
if (i <= harq->cb_segm.C - gamma - 1) { if (i <= cb_segm->C - gamma - 1) {
n_e = Qm * (Gp/harq->cb_segm.C); n_e = Qm * (Gp/cb_segm->C);
} else { } 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, 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); 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 */ /* 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 // Copy data
memcpy(&q->cb_in[F], &data[rp], (rlen - F) * sizeof(uint8_t)); memcpy(&q->cb_in[F], &data[rp], (rlen - F) * sizeof(uint8_t));
} else { } 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; q->cb_in[j] = 0;
} }
/* Attach Codeblock CRC */ /* Attach Codeblock CRC */
if (harq->cb_segm.C > 1) { if (cb_segm->C > 1) {
srslte_crc_attach(&q->crc_cb, q->cb_in, rlen); srslte_crc_attach(&q->crc_cb, q->cb_in, rlen);
} }
/* Set the filler bits to <NULL> */ /* 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 */ /* 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, (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"); fprintf(stderr, "Error in rate matching\n");
return SRSLTE_ERROR; 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 /* 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 parity[24];
uint8_t *p_parity = parity; uint8_t *p_parity = parity;
uint32_t par_rx, par_tx; uint32_t par_rx, par_tx;
uint32_t i; uint32_t i;
uint32_t cb_len, rp, wp, rlen, F, n_e; uint32_t cb_len, rp, wp, rlen, F, n_e;
uint32_t Qm = srslte_mod_bits_x_symbol(harq->mcs.mod);
if (q != NULL && if (q != NULL &&
data != NULL && data != NULL &&
harq != 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; 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 Gp = nof_e_bits / Qm;
uint32_t gamma=Gp; uint32_t gamma=Gp;
if (harq->cb_segm.C>0) { if (cb_segm->C>0) {
gamma = Gp%harq->cb_segm.C; gamma = Gp%cb_segm->C;
} }
bool early_stop = true; 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 */ /* Get read/write lengths */
if (i < harq->cb_segm.C2) { if (i < cb_segm->C2) {
cb_len = harq->cb_segm.K2; cb_len = cb_segm->K2;
} else { } 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; rlen = cb_len;
} else { } else {
rlen = cb_len - 24; rlen = cb_len - 24;
} }
if (i == 0) { if (i == 0) {
F = harq->cb_segm.F; F = cb_segm->F;
} else { } else {
F = 0; F = 0;
} }
if (i <= harq->cb_segm.C - gamma - 1) { if (i <= cb_segm->C - gamma - 1) {
n_e = Qm * (Gp/harq->cb_segm.C); n_e = Qm * (Gp/cb_segm->C);
} else { } 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, 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); cb_len, rlen - F, wp, rp, F, n_e);
/* Rate Unmatching */ /* 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, &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"); fprintf(stderr, "Error in rate matching\n");
return SRSLTE_ERROR; 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); srslte_tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len);
q->nof_iterations++; q->nof_iterations++;
if (harq->cb_segm.C > 1) { if (cb_segm->C > 1) {
len_crc = cb_len; len_crc = cb_len;
cb_in_ptr = q->cb_in; cb_in_ptr = q->cb_in;
crc_ptr = &q->crc_cb; crc_ptr = &q->crc_cb;
} else { } else {
len_crc = harq->mcs.tbs+24; len_crc = cb_segm->tbs+24;
cb_in_ptr = &q->cb_in[F]; cb_in_ptr = &q->cb_in[F];
crc_ptr = &q->crc_tb; 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 // 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 */ /* 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)); memcpy(&data[wp], &q->cb_in[F], (rlen - F) * sizeof(uint8_t));
} else { } else {
DEBUG("Last CB, appending parity: %d to %d from %d and 24 from %d\n", 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); INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp);
// Compute transport block CRC // 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 // check parity bits
par_tx = srslte_bit_unpack(&p_parity, 24); 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) { int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
return encode_tb(q, harq, data, e_bits, harq->nof_bits); 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 */ /* 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; 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; uint32_t idx = 0;
for(uint32_t j=0; j<rows; j++) { for(uint32_t j=0; j<rows; j++) {
for(uint32_t i=0; i<cols; i++) { for(uint32_t i=0; i<cols; i++) {
for(uint32_t k=0; k<Q_m; k++) { for(uint32_t k=0; k<Qm; k++) {
if (q_bits[j*Q_m + i*rows*Q_m + k] >= 10) { if (q_bits[j*Qm + i*rows*Qm + k] >= 10) {
q_bits[j*Q_m + i*rows*Q_m + k] -= 10; q_bits[j*Qm + i*rows*Qm + k] -= 10;
} else { } 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++; 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; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); 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,
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) 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; 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_cqi = 0;
uint32_t Q_prime_ack = 0; uint32_t Q_prime_ack = 0;
uint32_t Q_prime_ri = 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 = cfg->grant.nof_bits;
uint32_t nb_q = nof_symbols * Q_m; uint32_t Qm = cfg->grant.Qm;
bzero(q_bits, sizeof(uint8_t) * nb_q); bzero(q_bits, sizeof(uint8_t) * nb_q);
// Encode RI // Encode RI
if (uci_data.uci_ri_len > 0) { if (uci_data.uci_ri_len > 0) {
float beta = beta_ri_offset[uci_data.I_offset_ri]; 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]; 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) { if (ret < 0) {
return ret; return ret;
} }
@ -484,37 +535,39 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, srslte_harq_t *harq, uint8_t *data,
// Encode CQI // Encode CQI
if (uci_data.uci_cqi_len > 0) { if (uci_data.uci_cqi_len > 0) {
ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, cfg,
ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, uci_data.uci_cqi, uci_data.uci_cqi_len, uci_data.uci_cqi, uci_data.uci_cqi_len,
beta_cqi_offset[uci_data.I_offset_cqi], beta_cqi_offset[uci_data.I_offset_cqi],
Q_prime_ri, harq, g_bits); Q_prime_ri, g_bits);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
Q_prime_cqi = (uint32_t) ret; Q_prime_cqi = (uint32_t) ret;
} }
e_offset += Q_prime_cqi*Q_m; e_offset += Q_prime_cqi*Qm;
// Encode UL-SCH // Encode UL-SCH
if (harq->mcs.tbs > 0) { if (cfg->cb_segm.tbs > 0) {
uint32_t G = nb_q/Q_m - Q_prime_ri - Q_prime_cqi; uint32_t G = nb_q/Qm - Q_prime_ri - Q_prime_cqi;
ret = encode_tb(q, harq, data, &g_bits[e_offset], G*Q_m); ret = encode_tb(q, softbuffer, &cfg->cb_segm,
Qm, cfg->rv, G*Qm,
data, &g_bits[e_offset]);
if (ret) { if (ret) {
return ret; return ret;
} }
} }
// Interleave UL-SCH (and RI and CQI) // 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 // Encode (and interleave) ACK
if (uci_data.uci_ack_len > 0) { if (uci_data.uci_ack_len > 0) {
float beta = beta_harq_offset[uci_data.I_offset_ack]; 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]; 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) { if (ret < 0) {
return ret; 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); 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; 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 <math.h>
#include "srslte/phch/uci.h" #include "srslte/phch/uci.h"
#include "srslte/phch/harq.h" #include "srslte/fec/cbsegm.h"
#include "srslte/fec/convcoder.h" #include "srslte/fec/convcoder.h"
#include "srslte/fec/crc.h" #include "srslte/fec/crc.h"
#include "srslte/fec/rm_conv.h" #include "srslte/fec/rm_conv.h"
@ -114,23 +114,22 @@ 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) { static uint32_t Q_prime_cqi(srslte_pusch_cfg_t *cfg,
uint32_t M_sc = harq->ul_alloc.L_prb * SRSLTE_NRE; uint32_t O, float beta, uint32_t Q_prime_ri)
{
uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 + uint32_t K = cfg->cb_segm.C1*cfg->cb_segm.K1 + cfg->cb_segm.C2*cfg->cb_segm.K2;
harq->cb_segm.C2*harq->cb_segm.K2;
uint32_t Q_prime = 0; uint32_t Q_prime = 0;
if (K > 0) { uint32_t L = (O<11)?0:8;
uint32_t M_sc_init = harq->nof_prb * SRSLTE_NRE; uint32_t x = 999999;
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); if (K > 0) {
} else { x = (uint32_t) ceilf((float) (O+L)*cfg->grant.M_sc_init*cfg->grant.nof_symb*beta/K);
Q_prime = 12*harq->ul_alloc.L_prb*SRSLTE_NRE - Q_prime_ri;
} }
Q_prime = SRSLTE_MIN(x, cfg->grant.M_sc * cfg->grant.nof_symb - Q_prime_ri);
return Q_prime; 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 /* 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, int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, srslte_pusch_cfg_t *cfg,
srslte_harq_t *harq, uint8_t *q_bits) uint8_t *cqi_data, uint32_t cqi_len,
float beta, uint32_t Q_prime_ri,
uint8_t *q_bits)
{ {
if (beta < 0) { if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n"); fprintf(stderr, "Error beta is reserved\n");
return -1; 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; int ret = SRSLTE_ERROR;
if (cqi_len <= 11) { 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 { } 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) { if (ret) {
return 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 */ /* 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, 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) { uint8_t *q_bits) {
const uint32_t ack_column_set_norm[4] = {2, 3, 8, 9}; 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 row = H_prime_total/N_pusch_symbs-1-ack_q_bit_idx/4;
uint32_t colidx = (3*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]; 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++) { for(uint32_t k=0; k<Qm; k++) {
q_bits[row *Q_m + q_bits[row *Qm +
(H_prime_total/N_pusch_symbs)*col*Q_m + k] = ack_coded_bits[k]; (H_prime_total/N_pusch_symbs)*col*Qm + k] = ack_coded_bits[k];
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} else { } 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 */ /* 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, 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) { uint8_t *q_bits) {
static uint32_t ri_column_set_norm[4] = {1, 4, 7, 10}; 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 colidx = (3*ri_q_bit_idx)%4;
uint32_t col = SRSLTE_CP_ISNORM(cp)?ri_column_set_norm[colidx]:ri_column_set_ext[colidx]; 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); 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++) { for(uint32_t k=0; k<Qm; k++) {
q_bits[row *Q_m + (H_prime_total/N_pusch_symbs)*col*Q_m + k] = 10+ri_coded_bits[k]; q_bits[row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k] = 10+ri_coded_bits[k];
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} else { } 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) { if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n"); fprintf(stderr, "Error beta is reserved\n");
return -1; return -1;
} }
uint32_t M_sc = harq->ul_alloc.L_prb * SRSLTE_NRE; uint32_t K = cfg->cb_segm.C1*cfg->cb_segm.K1 + cfg->cb_segm.C2*cfg->cb_segm.K2;
uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 +
harq->cb_segm.C2*harq->cb_segm.K2;
// If not carrying UL-SCH, get Q_prime according to 5.2.4.1 // If not carrying UL-SCH, get Q_prime according to 5.2.4.1
if (K == 0) { 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*cfg->grant.M_sc_init*cfg->grant.nof_symb*beta/K);
uint32_t x = (uint32_t) ceilf((float) O*M_sc_init*harq->nof_symb*beta/K); uint32_t Q_prime = SRSLTE_MIN(x, 4*cfg->grant.M_sc);
uint32_t Q_prime = SRSLTE_MIN(x, 4*M_sc);
return Q_prime; 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[0] = data;
q_encoded_bits[1] = 2; 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; 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 /* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ * Currently only supporting 1-bit HARQ
*/ */
int srslte_uci_encode_ack(uint8_t data, uint32_t O_cqi, int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
float beta, srslte_harq_t *harq, uint8_t data,
uint32_t H_prime_total, uint8_t *q_bits) uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits)
{ {
if (beta < 0) { if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n"); fprintf(stderr, "Error beta is reserved\n");
return -1; return -1;
} }
uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod); uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq);
uint8_t q_encoded_bits[6]; 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++) { 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; 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 /* Encode UCI RI bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit RI * Currently only supporting 1-bit RI
*/ */
int srslte_uci_encode_ri(uint8_t data, uint32_t O_cqi, float beta, int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
srslte_harq_t *harq, uint32_t H_prime_total, uint8_t data,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits) uint8_t *q_bits)
{ {
if (beta < 0) { if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n"); fprintf(stderr, "Error beta is reserved\n");
return -1; return -1;
} }
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
uint32_t Q_m = srslte_mod_bits_x_symbol(harq->mcs.mod);
uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq);
uint8_t q_encoded_bits[6]; 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++) { 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; return (int) Qprime;

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

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

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

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

@ -57,13 +57,8 @@ uint32_t sf_idx = 0;
srslte_dci_format_t dci_format = SRSLTE_DCI_FORMAT1A; srslte_dci_format_t dci_format = SRSLTE_DCI_FORMAT1A;
srslte_filesource_t fsrc; srslte_filesource_t fsrc;
srslte_pdcch_t pdcch; srslte_ue_dl_t ue_dl;
srslte_pdsch_t pdsch; cf_t *input_buffer;
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;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [rovfcenmps] -i input_file\n", 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 base_init() {
int i;
if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) { if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
fprintf(stderr, "Error opening file %s\n", input_file_name); fprintf(stderr, "Error opening file %s\n", input_file_name);
@ -147,98 +141,31 @@ int base_init() {
exit(-1); exit(-1);
} }
fft_buffer = malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); if (srslte_ue_dl_init(&ue_dl, cell)) {
if (!fft_buffer) { fprintf(stderr, "Error initializing UE DL\n");
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);
return -1; return -1;
} }
if (srslte_pdcch_init(&pdcch, &regs, cell)) { srslte_ue_dl_set_rnti(&ue_dl, rnti);
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);
}
DEBUG("Memory init OK\n",0); DEBUG("Memory init OK\n",0);
return 0; return 0;
} }
void base_free() { void base_free() {
int i;
srslte_filesource_free(&fsrc); srslte_filesource_free(&fsrc);
srslte_ue_dl_free(&ue_dl);
free(input_buffer); 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);
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
srslte_ra_pdsch_t ra_dl;
int i;
int nof_frames; int nof_frames;
int ret; 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) { if (argc < 3) {
usage(argv[0]); usage(argv[0]);
exit(-1); exit(-1);
} }
parse_args(argc,argv); parse_args(argc,argv);
if (base_init()) { if (base_init()) {
@ -246,10 +173,7 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (rnti == SRSLTE_SIRNTI) { uint8_t *data = malloc(100000);
INFO("Initializing common search space for SI-RNTI\n",0);
nof_locations = srslte_pdcch_common_locations(&pdcch, locations, MAX_CANDIDATES, cfi);
}
ret = -1; ret = -1;
nof_frames = 0; nof_frames = 0;
@ -257,56 +181,22 @@ int main(int argc, char **argv) {
srslte_filesource_read(&fsrc, input_buffer, flen); srslte_filesource_read(&fsrc, input_buffer, flen);
INFO("Reading %d samples sub-frame %d\n", flen, sf_idx); INFO("Reading %d samples sub-frame %d\n", flen, sf_idx);
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); ret = srslte_ue_dl_decode(&ue_dl, input_buffer, data, sf_idx);
if(ret > 0) {
/* Get channel estimates for each port */ printf("PDSCH Decoded OK!\n");
srslte_chest_dl_estimate(&chest, fft_buffer, ce, sf_idx); } else if (ret == 0) {
printf("No DCI grant found\n");
if (rnti != SRSLTE_SIRNTI) { } else if (ret < 0) {
INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti); printf("Error decoding PDSCH\n");
nof_locations = srslte_pdcch_ue_locations(&pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti);
} }
sf_idx = (sf_idx+1)%10;
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;
}
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;
}
nof_frames++; nof_frames++;
} while (nof_frames <= max_frames); } while (nof_frames <= max_frames && ret == 0);
ret = 0;
goout:
base_free(); 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; uint32_t i, j;
uint8_t *data = NULL; uint8_t *data = NULL;
cf_t *ce[SRSLTE_MAX_PORTS]; cf_t *ce[SRSLTE_MAX_PORTS];
uint32_t nof_re;
cf_t *slot_symbols[SRSLTE_MAX_PORTS]; cf_t *slot_symbols[SRSLTE_MAX_PORTS];
int ret = -1; int ret = -1;
struct timeval t[3]; struct timeval t[3];
srslte_ra_mcs_t mcs; srslte_pdsch_cfg_t pdsch_cfg;
srslte_ra_dl_alloc_t prb_alloc; srslte_softbuffer_tx_t softbuffer_tx;
srslte_harq_t harq_process; srslte_softbuffer_rx_t softbuffer_rx;
uint32_t rv; uint32_t rv;
parse_args(argc,argv); parse_args(argc,argv);
bzero(&pdsch, sizeof(srslte_pdsch_t)); 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(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
bzero(slot_symbols, 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; pdsch_cfg.grant.nof_prb = cell.nof_prb;
for (i=0;i<prb_alloc.slot[0].nof_prb;i++) { for (i=0;i<pdsch_cfg.grant.nof_prb;i++) {
prb_alloc.slot[0].prb_idx[i] = true; 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_ra_dl_alloc_re(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp); 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;
/* init memory */ /* init memory */
for (i=0;i<cell.nof_ports;i++) { 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]) { if (!ce[i]) {
perror("malloc"); perror("malloc");
goto quit; goto quit;
} }
for (j=0;j<nof_re;j++) { for (j=0;j<pdsch_cfg.grant.nof_re;j++) {
ce[i][j] = 1; 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]) { if (!slot_symbols[i]) {
perror("malloc"); perror("malloc");
goto quit; goto quit;
@ -185,33 +189,35 @@ int main(int argc, char **argv) {
srslte_pdsch_set_rnti(&pdsch, 1234); srslte_pdsch_set_rnti(&pdsch, 1234);
if (srslte_harq_init(&harq_process, cell)) { if (srslte_softbuffer_tx_init(&softbuffer_tx, cell)) {
fprintf(stderr, "Error initiating HARQ process\n"); fprintf(stderr, "Error initiating TX soft buffer\n");
goto quit; goto quit;
} }
for (mcs.tbs = tbs;mcs.tbs<=tbs+nof_tbs;mcs.tbs++) { if (srslte_softbuffer_rx_init(&softbuffer_rx, cell)) {
fprintf(stderr, "Error initiating RX soft buffer\n");
goto quit;
}
for (pdsch_cfg.grant.mcs.tbs = tbs;pdsch_cfg.grant.mcs.tbs<=tbs+nof_tbs;pdsch_cfg.grant.mcs.tbs++) {
if (SRSLTE_VERBOSE_ISNONE()) { 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; data[i] = rand()%2;
} }
for (rv=0;rv<=rv_idx;rv++) { for (rv=0;rv<=rv_idx;rv++) {
if (srslte_harq_setup_dl(&harq_process, mcs, rv, subframe, &prb_alloc)) { srslte_cbsegm(&pdsch_cfg.cb_segm, pdsch_cfg.grant.mcs.tbs);
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
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"); fprintf(stderr, "Error encoding PDSCH\n");
goto quit; goto quit;
} }
/* combine outputs */ /* combine outputs */
for (i=0;i<cell.nof_ports;i++) { 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) { if (i > 0) {
slot_symbols[0][j] += slot_symbols[i][j]; slot_symbols[0][j] += slot_symbols[i][j];
} }
@ -220,16 +226,16 @@ int main(int argc, char **argv) {
} }
gettimeofday(&t[1], NULL); 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); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
if (r) { if (r) {
printf("Error decoding TBS: %d\n", mcs.tbs); printf("Error decoding TBS: %d\n", pdsch_cfg.grant.mcs.tbs);
ret = -1; ret = -1;
goto quit; goto quit;
} else { } else {
if (nof_tbs == 0) { 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; ret = 0;
quit: quit:
srslte_pdsch_free(&pdsch); 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++) { for (i=0;i<cell.nof_ports;i++) {
if (ce[i]) { if (ce[i]) {

@ -54,20 +54,20 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_pdsch_t pdsch; srslte_pdsch_t pdsch;
srslte_chest_dl_t chest; srslte_chest_dl_t chest;
srslte_ofdm_t fft; srslte_ofdm_t fft;
uint32_t cfi, sf_idx;
cf_t *input_fft, *input_signal; cf_t *input_fft, *input_signal;
int nof_re; int nof_re;
srslte_ra_mcs_t mcs; srslte_pdsch_cfg_t cfg;
srslte_ra_dl_alloc_t dl_alloc; srslte_softbuffer_rx_t softbuffer;
srslte_harq_t harq_process;
uint32_t rv;
uint32_t rnti32; uint32_t rnti32;
uint32_t cfi;
if (nrhs < NOF_INPUTS) { if (nrhs < NOF_INPUTS) {
help(); help();
return; return;
} }
bzero(&cfg, sizeof(srslte_pdsch_cfg_t));
if (mexutils_read_cell(ENBCFG, &cell)) { if (mexutils_read_cell(ENBCFG, &cell)) {
help(); help();
return; return;
@ -82,7 +82,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
help(); help();
return; return;
} }
if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &sf_idx)) { if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &cfg.sf_idx)) {
help(); help();
return; 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)); srslte_pdsch_set_rnti(&pdsch, (uint16_t) (rnti32 & 0xffff));
if (srslte_harq_init(&harq_process, cell)) { if (srslte_softbuffer_rx_init(&softbuffer, cell)) {
mexErrMsgTxt("Error initiating HARQ process\n"); mexErrMsgTxt("Error initiating soft buffer\n");
return; return;
} }
@ -108,16 +108,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE; nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE;
mcs.tbs = mxGetScalar(TBS); cfg.grant.mcs.tbs = mxGetScalar(TBS);
if (mcs.tbs == 0) { if (cfg.grant.mcs.tbs == 0) {
mexErrMsgTxt("Error trblklen is zero\n"); mexErrMsgTxt("Error trblklen is zero\n");
return; 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"); mexErrMsgTxt("Field RV not found in pdsch config\n");
return; 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"); char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) { if (!strcmp(mod_str, "QPSK")) {
mcs.mod = SRSLTE_MOD_QPSK; cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) { } else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM; cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) { } else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM; cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
} else { } else {
mexErrMsgTxt("Unknown modulation\n"); mexErrMsgTxt("Unknown modulation\n");
return; return;
@ -146,26 +149,27 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
// Only localized PRB supported // 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++) { for (i=0;i<cell.nof_prb;i++) {
dl_alloc.slot[0].prb_idx[i] = false; cfg.grant.prb_idx[0][i] = false;
for (int j=0;j<dl_alloc.slot[0].nof_prb && !dl_alloc.slot[0].prb_idx[i];j++) { for (int j=0;j<cfg.grant.nof_prb && !cfg.grant.prb_idx[0][i];j++) {
if ((int) prbset[j] == i) { 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); 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)) { // Fill rest of grant structure
mexErrMsgTxt("Error configuring HARQ process\n"); cfg.grant.lstart = cell.nof_prb<10?(cfi+1):cfi;
return; 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 */ /** Allocate input buffers */
if (mexutils_read_cf(INPUT, &input_signal) < 0) { if (mexutils_read_cf(INPUT, &input_signal) < 0) {
@ -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)); 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]; cf_t *ce[SRSLTE_MAX_PORTS];
for (i=0;i<cell.nof_ports;i++) { 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)); 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) if (cearray_ptr)
free(cearray_ptr); free(cearray_ptr);
} else { } 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; float noise_power;
if (nrhs > NOF_INPUTS + 1) { 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); 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) { if (!data) {
return; 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) { if (nlhs >= 1) {
plhs[0] = mxCreateLogicalScalar(r == 0); plhs[0] = mxCreateLogicalScalar(r == 0);
} }
if (nlhs >= 2) { 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) { 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) { 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) { 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); srslte_chest_dl_free(&chest);

@ -261,7 +261,7 @@ int main(int argc, char **argv) {
exit(-1); 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); ngroup, nseq, ack_rx, numsubframe, distance);
} }
} }

@ -186,7 +186,7 @@ int main(int argc, char **argv) {
printf("Error decoding ACK\n"); printf("Error decoding ACK\n");
exit(-1); 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); ngroup, nseq, ack[ngroup][nseq], ack_rx, nsf, distance);
if (ack[ngroup][nseq] != ack_rx) { if (ack[ngroup][nseq] != ack_rx) {
printf("Invalid received ACK: %d!=%d\n", 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[])
srslte_pusch_cfg_t cfg;
uint32_t sf_idx=0; bzero(&cfg, sizeof(srslte_pusch_cfg_t));
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) { if (mexutils_read_uint32_struct(UECFG, "NSubframe", &cfg.sf_idx)) {
mexErrMsgTxt("Field NSubframe not found in UE config\n"); mexErrMsgTxt("Field NSubframe not found in UE config\n");
return; return;
} }
srslte_ra_mcs_t mcs;
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) { if (!strcmp(mod_str, "QPSK")) {
mcs.mod = SRSLTE_MOD_QPSK; cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) { } else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM; cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) { } else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM; cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
} else { } else {
mexErrMsgTxt("Unknown modulation\n"); mexErrMsgTxt("Unknown modulation\n");
return; return;
@ -108,26 +107,31 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Error field PRBSet not found\n"); mexErrMsgTxt("Error field PRBSet not found\n");
return; return;
} }
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;
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];
free(prbset); 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; 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; srslte_softbuffer_tx_t softbuffer;
if (srslte_harq_init(&harq_process, cell)) { if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
mexErrMsgTxt("Error initiating HARQ process\n"); mexErrMsgTxt("Error initiating soft buffer\n");
return; return;
} }
if (srslte_harq_setup_ul(&harq_process, mcs, 0, sf_idx, &prb_alloc)) { if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
mexErrMsgTxt("Error configuring HARQ process\n"); mexErrMsgTxt("Error computing CB segmentation\n");
return; return;
} }
@ -156,36 +160,39 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
free(tmp); 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; 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; 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; 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); uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ack, uci_data.uci_ri_len, uci_data.uci_ri);
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", harq_process.nof_re, harq_process.nof_bits, harq_process.mcs.tbs); 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, &harq_process, trblkin, uci_data, sf_symbols); int r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols);
if (r < 0) { if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n"); mexErrMsgTxt("Error encoding PUSCH\n");
return; return;
} }
uint32_t rv=0; if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &cfg.rv)) {
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) {
mexErrMsgTxt("Field RV not found in pdsch config\n"); mexErrMsgTxt("Field RV not found in pdsch config\n");
return; return;
} }
if (rv > 0) { if (cfg.rv > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv, sf_idx, &prb_alloc)) { r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols);
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols);
if (r < 0) { if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n"); mexErrMsgTxt("Error encoding PUSCH\n");
return; 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); mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1);
} }
if (nlhs >= 3) { 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); srslte_pusch_free(&pusch);
free(trblkin); free(trblkin);

@ -135,16 +135,34 @@ int main(int argc, char **argv) {
cf_t *sf_symbols = NULL; cf_t *sf_symbols = NULL;
int ret = -1; int ret = -1;
struct timeval t[3]; struct timeval t[3];
srslte_ra_mcs_t mcs; srslte_pusch_cfg_t cfg;
srslte_ra_ul_alloc_t prb_alloc; srslte_softbuffer_tx_t softbuffer;
srslte_harq_t harq_process;
parse_args(argc,argv); parse_args(argc,argv);
mcs.tbs = tbs; bzero(&cfg, sizeof(srslte_pusch_cfg_t));
mcs.mod = modulation;
bzero(&prb_alloc, sizeof(srslte_ra_ul_alloc_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)) { if (srslte_pusch_init(&pusch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
@ -152,12 +170,14 @@ int main(int argc, char **argv) {
} }
srslte_pusch_set_rnti(&pusch, 1234); srslte_pusch_set_rnti(&pusch, 1234);
if (srslte_harq_init(&harq_process, cell)) { if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
fprintf(stderr, "Error initiating HARQ process\n"); fprintf(stderr, "Error initiating soft buffer\n");
goto quit; goto quit;
} }
printf("Encoding rv_idx=%d\n",rv_idx); printf("Encoding rv_idx=%d\n",rv_idx);
cfg.rv = 0;
cfg.sf_idx = subframe;
uint8_t tmp[20]; uint8_t tmp[20];
for (uint32_t i=0;i<20;i++) { 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)); bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_data.I_offset_cqi = 7; uci_data.I_offset_cqi = 7;
uci_data.I_offset_ri = 2; 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_ri_len = 0;
uci_data.uci_ack_len = 0; uci_data.uci_ack_len = 1;
uci_data.uci_cqi = tmp; uci_data.uci_cqi = tmp;
uci_data.uci_ri = 1; uci_data.uci_ri = 0;
uci_data.uci_ack = 1; 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)) { if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
fprintf(stderr, "Error configuring HARQ process\n"); fprintf(stderr, "Error configuring CB segmentation\n");
goto quit; goto quit;
} }
srslte_pusch_hopping_cfg_t ul_hopping; srslte_pusch_hopping_cfg_t ul_hopping;
@ -206,34 +216,29 @@ int main(int argc, char **argv) {
goto quit; goto quit;
} }
data = malloc(sizeof(uint8_t) * mcs.tbs); data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs);
if (!data) { if (!data) {
perror("malloc"); perror("malloc");
goto quit; 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; 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"); fprintf(stderr, "Error encoding TB\n");
exit(-1); exit(-1);
} }
if (rv_idx > 0) { if (rv_idx > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv_idx, subframe, &prb_alloc)) { cfg.rv = rv_idx;
fprintf(stderr, "Error configuring HARQ process\n"); if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, data, uci_data, sf_symbols)) {
goto quit;
}
if (srslte_pusch_uci_encode(&pusch, &harq_process, data, uci_data, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n"); fprintf(stderr, "Error encoding TB\n");
exit(-1); exit(-1);
} }
} }
cf_t *scfdma = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); 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)); bzero(scfdma, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_ofdm_t fft; srslte_ofdm_t fft;
@ -251,13 +256,13 @@ int main(int argc, char **argv) {
ret = -1; ret = -1;
goto quit; goto quit;
} else { } 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; ret = 0;
quit: quit:
srslte_pusch_free(&pusch); srslte_pusch_free(&pusch);
srslte_harq_free(&harq_process); srslte_softbuffer_tx_free(&softbuffer);
if (sf_symbols) { if (sf_symbols) {
free(sf_symbols); free(sf_symbols);

@ -48,17 +48,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ {
srslte_sch_t ulsch; srslte_sch_t ulsch;
uint8_t *trblkin; uint8_t *trblkin;
srslte_ra_mcs_t mcs; srslte_pusch_cfg_t cfg;
srslte_ra_ul_alloc_t prb_alloc; srslte_softbuffer_tx_t softbuffer;
srslte_harq_t harq_process;
uint32_t rv;
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
uint32_t rv;
if (nrhs < NOF_INPUTS) { if (nrhs < NOF_INPUTS) {
help(); help();
return; return;
} }
bzero(&cfg, sizeof(srslte_pusch_cfg_t));
if (srslte_sch_init(&ulsch)) { if (srslte_sch_init(&ulsch)) {
mexErrMsgTxt("Error initiating ULSCH\n"); mexErrMsgTxt("Error initiating ULSCH\n");
return; return;
@ -67,12 +68,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cell.nof_prb = 100; cell.nof_prb = 100;
cell.id=1; cell.id=1;
cell.cp=SRSLTE_CP_NORM; cell.cp=SRSLTE_CP_NORM;
if (srslte_harq_init(&harq_process, cell)) {
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
mexErrMsgTxt("Error initiating HARQ\n"); mexErrMsgTxt("Error initiating HARQ\n");
return; 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); uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &uci_data.uci_cqi);
uint8_t *tmp; uint8_t *tmp;
@ -87,7 +89,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
free(tmp); 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); uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ri_len);
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) { if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) {
@ -95,24 +97,31 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; 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; 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; 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; 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"); char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) { if (!strcmp(mod_str, "QPSK")) {
mcs.mod = SRSLTE_MOD_QPSK; cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) { } else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM; cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) { } else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM; cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
} else { } else {
mexErrMsgTxt("Unknown modulation\n"); mexErrMsgTxt("Unknown modulation\n");
return; return;
@ -128,49 +137,56 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
prb_alloc.L_prb = mexutils_read_f(p, &prbset); cfg.grant.L_prb = mexutils_read_f(p, &prbset);
prb_alloc.n_prb[0] = prbset[0]; cfg.grant.n_prb[0] = prbset[0];
prb_alloc.n_prb[1] = prbset[0]; cfg.grant.n_prb[1] = prbset[0];
free(prbset); free(prbset);
cfg.grant.L_prb = mexutils_read_f(p, &prbset);
mexPrintf("Q_m: %d, NPRB: %d, RV: %d\n", srslte_mod_bits_x_symbol(mcs.mod), prb_alloc.L_prb, rv); cfg.grant.n_prb[0] = prbset[0];
cfg.grant.n_prb[1] = prbset[0];
if (srslte_harq_setup_ul(&harq_process, mcs, 0, 0, &prb_alloc)) { 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;
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"); mexErrMsgTxt("Error configuring HARQ process\n");
return; 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) { if (!q_bits) {
return; 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) { if (!g_bits) {
return; 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"); mexErrMsgTxt("Error encoding TB\n");
return; return;
} }
if (rv > 0) { if (rv > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv, 0, &prb_alloc)) { cfg.rv = rv;
mexErrMsgTxt("Error configuring HARQ process\n"); if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits)) {
return;
}
if (srslte_ulsch_uci_encode(&ulsch, &harq_process, trblkin, uci_data, g_bits, q_bits)) {
mexErrMsgTxt("Error encoding TB\n"); mexErrMsgTxt("Error encoding TB\n");
return; return;
} }
} }
if (nlhs >= 1) { 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_sch_free(&ulsch);
srslte_harq_free(&harq_process); srslte_softbuffer_tx_free(&softbuffer);
free(trblkin); free(trblkin);
free(g_bits); free(g_bits);

@ -286,7 +286,7 @@ int main(int argc, char **argv) {
frame_cnt++; frame_cnt++;
printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " 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, frame_cnt,
peak_idx, peak_idx,
peak_value, mean_peak, peak_value, mean_peak,

@ -296,7 +296,7 @@ int main(int argc, char **argv) {
frame_cnt++; frame_cnt++;
printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " 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, frame_cnt,
peak_idx, peak_idx,
peak_value, mean_peak, 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"); fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit; goto clean_exit;
} }
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) { if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell)) {
if (srslte_harq_init(&q->harq_process[i], q->cell)) { fprintf(stderr, "Error initiating soft buffer\n");
fprintf(stderr, "Error initiating HARQ process\n"); goto clean_exit;
goto clean_exit;
}
} }
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols) { if (!q->sf_symbols) {
@ -125,9 +123,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
srslte_phich_free(&q->phich); srslte_phich_free(&q->phich);
srslte_pdcch_free(&q->pdcch); srslte_pdcch_free(&q->pdcch);
srslte_pdsch_free(&q->pdsch); srslte_pdsch_free(&q->pdsch);
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) { srslte_softbuffer_rx_free(&q->softbuffer);
srslte_harq_free(&q->harq_process[i]);
}
if (q->sf_symbols) { if (q->sf_symbols) {
free(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]); free(q->ce[i]);
} }
} }
bzero(q, sizeof(srslte_ue_dl_t)); 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) { 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 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; int ret = SRSLTE_ERROR;
q->nof_detected++; 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"); fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (srslte_cbsegm(&q->pdsch_cfg.cb_segm, q->pdsch_cfg.grant.mcs.tbs)) {
if (rnti != SRSLTE_SIRNTI) { fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", q->pdsch_cfg.grant.mcs.tbs);
rvidx = q->ra_dl.rv_idx;
}
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; return SRSLTE_ERROR;
} }
if (q->harq_process[0].mcs.mod > 0 && q->harq_process[0].mcs.tbs >= 0) { q->pdsch_cfg.sf_idx = sf_idx;
ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->harq_process[0], q->sf_symbols, if (rnti == SRSLTE_SIRNTI) {
q->ce, 0, q->pdsch_cfg.rv = rvidx;
rnti, data); } else {
q->pdsch_cfg.rv = dl_dci.rv_idx;
}
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) { if (ret == SRSLTE_ERROR) {
q->pkt_errors++; 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) { } else if (ret == SRSLTE_SUCCESS) {
if (SRSLTE_VERBOSE_ISINFO()) { if (SRSLTE_VERBOSE_ISINFO()) {
INFO("Decoded Message: ", 0); 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++; 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) { if (found_dci == 1 && ret == SRSLTE_SUCCESS) {
return q->ra_dl.mcs.tbs; return q->pdsch_cfg.grant.mcs.tbs;
} else { } else {
return 0; return 0;
} }

@ -39,7 +39,7 @@
int srslte_ue_ul_init(srslte_ue_ul_t *q, int srslte_ue_ul_init(srslte_ue_ul_t *q,
srslte_cell_t cell) srslte_cell_t cell)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; 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"); fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit; goto clean_exit;
} }
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) { if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell)) {
if (srslte_harq_init(&q->harq_process[i], q->cell)) { fprintf(stderr, "Error initiating soft buffer\n");
fprintf(stderr, "Error initiating HARQ process\n"); goto clean_exit;
goto clean_exit;
}
} }
if (srslte_refsignal_ul_init(&q->dmrs, cell)) { if (srslte_refsignal_ul_init(&q->dmrs, cell)) {
fprintf(stderr, "Error initiating srslte_refsignal_ul\n"); 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_ofdm_rx_free(&q->fft);
srslte_pusch_free(&q->pusch); srslte_pusch_free(&q->pusch);
srslte_pucch_free(&q->pucch); srslte_pucch_free(&q->pucch);
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) { srslte_softbuffer_tx_free(&q->softbuffer);
srslte_harq_free(&q->harq_process[i]);
}
srslte_cfo_free(&q->cfo); srslte_cfo_free(&q->cfo);
srslte_refsignal_ul_free(&q->dmrs); 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) { 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, void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg, srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_pusch_hopping_cfg_t *pusch_hopping_cfg, srslte_pusch_hopping_cfg_t *pusch_hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg, srslte_pucch_cfg_t *pucch_cfg,
srslte_pucch_sched_t *pucch_sched) srslte_pucch_sched_t *pucch_sched)
{ {
srslte_refsignal_ul_set_pusch_cfg(&q->dmrs, dmrs_cfg); srslte_refsignal_ul_set_pusch_cfg(&q->dmrs, dmrs_cfg);
srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_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) { if (q->normalize_en) {
uint32_t n_prb = 1; float norm_factor = (float) q->cell.nof_prb/10;
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);
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); 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)); 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; 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; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); 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; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); 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, int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant,
uint32_t sf_idx, uint16_t rnti, uint8_t *data, srslte_uci_data_t uci_data,
cf_t *output_signal) uint32_t sf_idx, uint32_t rv, uint16_t rnti,
cf_t *output_signal)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
ra_ul != NULL && grant != NULL &&
data != NULL && data != NULL &&
output_signal != 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"); fprintf(stderr, "Invalid UL PRB allocation (L_prb=0)\n");
return ret; return ret;
} }
ret = SRSLTE_ERROR; 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)) { memcpy(&q->pusch_cfg.grant, grant, sizeof(srslte_ra_ul_grant_t));
fprintf(stderr, "Error configuring HARQ process\n"); q->pusch_cfg.sf_idx = sf_idx;
return ret; q->pusch_cfg.rv = rv;
} q->pusch_cfg.cp = q->cell.cp;
srslte_cbsegm(&q->pusch_cfg.cb_segm, grant->mcs.tbs);
if (srslte_pusch_encode_rnti(&q->pusch, &q->harq_process[0], data, rnti, q->sf_symbols)) { 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"); fprintf(stderr, "Error encoding TB\n");
return ret; return ret;
} }
// FIXME: Pregenerate for all possible number of prb // 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"); fprintf(stderr, "Error generating PUSCH DRMS signals\n");
return ret; return ret;
} }
srslte_refsignal_dmrs_pusch_put(&q->dmrs, q->refsignal, srslte_refsignal_dmrs_pusch_put(&q->dmrs, q->refsignal,
q->harq_process[0].ul_alloc.L_prb, cfg->grant.L_prb,
q->harq_process[0].ul_alloc.n_prb_tilde, cfg->grant.n_prb_tilde,
q->sf_symbols); q->sf_symbols);
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); 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) { 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)); 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; 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 (signal_buffer) {
if (!sf_symbols_and_ce_done) { 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; return false;
} }
if (srslte_dci_msg_to_ra_ul(&dci_msg, cell.nof_prb, return grant->create_from_dci(&dci_msg, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET),
(srslte_ra_pusch_t*) grant->get_grant_ptr()))
{
return false;
}
return true;
} }
} }
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()) { if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Getting DL grant\n", tti); 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; return false;
} }
grant->set_ncce(srslte_ue_dl_get_ncce(&ue_dl)); return grant->create_from_dci(&dci_msg, cell, cfi, tti%10, 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;
} }
} }
bool dl_buffer::decode_ack(sched_grant pusch_grant) bool dl_buffer::decode_ack(ul_sched_grant *grant)
{ {
if (signal_buffer && is_ready()) { if (signal_buffer && is_ready()) {
if (!sf_symbols_and_ce_done) { 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; 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, grant->get_I_lowest(), grant->get_n_dmrs());
return srslte_ue_dl_decode_phich(&ue_dl, tti%10, ra_ul->prb_alloc.n_prb[0], ra_ul->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()) { if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Decoding PDSCH\n", tti); 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; sf_symbols_and_ce_done = true;
} }
srslte_ra_pdsch_t *ra_dl = (srslte_ra_pdsch_t*) pdsch_grant.get_grant_ptr(); grant->get_pdsch_cfg(tti%10, &ue_dl.pdsch_cfg);
if (srslte_harq_setup_dl(&ue_dl.harq_process[0], ra_dl->mcs, if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) {
ra_dl->rv_idx, tti%10, &ra_dl->prb_alloc)) { int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, &ue_dl.softbuffer, ue_dl.sf_symbols,
fprintf(stderr, "Error configuring HARQ process\n"); ue_dl.ce, 0, grant->get_rnti(), payload);
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);
if (SRSLTE_VERBOSE_ISINFO()) { 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) { if (ret == SRSLTE_SUCCESS) {
return true; 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); 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); 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(); grant->create_from_rar(rar, cell, 0, params_db.get_param(phy_params::PUSCH_HOPPING_OFFSET));
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);
}
} }
void phy::set_param(phy_params::phy_param_t param, int64_t value) { void phy::set_param(phy_params::phy_param_t param, int64_t value) {

@ -51,7 +51,7 @@ void prach::free_cell()
free(signal_buffer); free(signal_buffer);
} }
srslte_cfo_free(&cfo_h); 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_; cell = cell_;
params_db = params_db_; params_db = params_db_;
preamble_idx = -1; 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)), 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_ROOT_SEQ_IDX),
params_db->get_param(phy_params::PRACH_HIGH_SPEED_FLAG)?true:false, 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; 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++) { for (uint32_t i=0;i<64;i++) {
buffer[i] = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t)); buffer[i] = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t));
if(!buffer[i]) { if(!buffer[i]) {
return false; 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; 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_len = 1;
uci_data.uci_ack = ack?1:0; uci_data.uci_ack = ack?1:0;
uci_pending = true; 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]) bool ul_buffer::generate_ack(bool ack[2])
@ -89,11 +89,11 @@ bool ul_buffer::uci_ready() {
} }
bool ul_buffer::generate_data() { bool ul_buffer::generate_data() {
sched_grant dummy(sched_grant::DOWNLINK, 0); ul_sched_grant dummy(0);
return generate_data(dummy, NULL); 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) uint8_t *payload)
{ {
if (is_ready()) { 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_INTRA_SF :
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET); 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; srslte_pucch_cfg_t pucch_cfg;
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t)); bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
@ -145,10 +145,12 @@ bool ul_buffer::generate_data(sched_grant pusch_grant,
int n = 0; int n = 0;
// Transmit on PUSCH if UL grant available, otherwise in PUCCH // Transmit on PUSCH if UL grant available, otherwise in PUCCH
if (payload) { if (payload) {
n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(),
payload, uci_data, grant->to_pusch_cfg(tti%10, cell.cp, &pusch_cfg);
tti%10, pusch_grant.get_rnti(), n = srslte_ue_ul_pusch_encode_cfg(&ue_ul, &pusch_cfg,
signal_buffer); payload, uci_data,
grant->get_rnti(),
signal_buffer);
} else { } else {
n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer); n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer);
} }

@ -214,6 +214,7 @@ 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_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_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_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::PUSCH_HOPPING_OFFSET, 0);
phy.set_param(srslte::ue::phy_params::PUCCH_BETA, 10); phy.set_param(srslte::ue::phy_params::PUCCH_BETA, 10);
@ -253,7 +254,7 @@ void run_tti(uint32_t tti) {
} }
} }
if (state == RAR) { 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(); int ra_tti = phy.get_prach_transmitted_tti();
if (ra_tti > 0) { if (ra_tti > 0) {
INFO("PRACH was transmitted at %d\n", ra_tti); 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)) if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant))
{ {
// Decode packet // Decode packet
if (dl_buffer->decode_data(rar_grant, payload)) { if (dl_buffer->decode_data(&rar_grant, payload)) {
rar_unpack(payload, &rar_msg); rar_unpack(payload, &rar_msg);
if (!prog_args.continous) { if (!prog_args.continous) {
printf("Received RAR for preamble %d\n", rar_msg.RAPID); 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); phy.set_timeadv_rar(rar_msg.timing_adv_cmd);
// Generate Msg3 grant // Generate Msg3 grant
srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti); srslte::ue::ul_sched_grant connreq_grant(rar_msg.temp_c_rnti);
phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant); 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 // Pack Msg3 bits
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs()); 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) { if (ul_buffer) {
connreq_grant.set_rv(0); connreq_grant.set_rv(0);
INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti); 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 // Save transmission time
conreq_tti = ul_buffer->tti; conreq_tti = ul_buffer->tti;
@ -318,11 +323,15 @@ void run_tti(uint32_t tti) {
uint32_t interval_conreq = interval(tti, conreq_tti); uint32_t interval_conreq = interval(tti, conreq_tti);
if (interval_conreq == 4) { if (interval_conreq == 4) {
srslte::ue::sched_grant connreq_grant(srslte::ue::sched_grant::UPLINK, rar_msg.temp_c_rnti); srslte::ue::ul_sched_grant connreq_grant(rar_msg.temp_c_rnti);
phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant); 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 // Decode PHICH from Connection Request
if (!dl_buffer->decode_ack(connreq_grant)) { if (!dl_buffer->decode_ack(&connreq_grant)) {
// Pack Msg3 bits // Pack Msg3 bits
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs()); 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_current_tx_nb(nof_rtx_connsetup);
connreq_grant.set_rv(rv_value[nof_rtx_connsetup%4]); connreq_grant.set_rv(rv_value[nof_rtx_connsetup%4]);
INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti); 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 // Save transmission time
conreq_tti = ul_buffer->tti; conreq_tti = ul_buffer->tti;
@ -354,13 +363,13 @@ void run_tti(uint32_t tti) {
} }
} }
if (state == CONNSETUP) { 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; bool connsetup_recv = false;
// Get DL grant for tmp_rnti // Get DL grant for tmp_rnti
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant)) if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant))
{ {
// Decode packet // Decode packet
if (dl_buffer->decode_data(conn_setup_grant, payload)) { if (dl_buffer->decode_data(&conn_setup_grant, payload)) {
nof_rx_connsetup++; nof_rx_connsetup++;
state = RA; state = RA;
nof_rtx_connsetup=0; nof_rtx_connsetup=0;
@ -375,7 +384,7 @@ void run_tti(uint32_t tti) {
// send ACK // send ACK
INFO("Sending ack %d on TTI: %d\n", connsetup_recv, tti+4); INFO("Sending ack %d on TTI: %d\n", connsetup_recv, tti+4);
srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(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) { if (!prog_args.continous) {
while(ul_buffer->uci_ready()) { while(ul_buffer->uci_ready()) {
sleep(1); sleep(1);

@ -92,7 +92,7 @@ uint8_t payload[1024];
// This is the MAC implementation // This is the MAC implementation
void run_tti(uint32_t tti) { 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); INFO("MAC running tti: %d\n", tti);
// SIB1 is scheduled in subframe #5 of even frames // SIB1 is scheduled in subframe #5 of even frames
@ -108,7 +108,7 @@ void run_tti(uint32_t tti) {
grant.set_rv(((uint32_t) ceilf((float)3*((phy.tti_to_SFN(tti)/2)%4)/2))%4); grant.set_rv(((uint32_t) ceilf((float)3*((phy.tti_to_SFN(tti)/2)%4)/2))%4);
// Decode packet // Decode packet
if (!buffer->decode_data(grant, payload)) { if (!buffer->decode_data(&grant, payload)) {
total_errors++; total_errors++;
} }
} }
@ -141,6 +141,12 @@ int main(int argc, char *argv[])
// Give it time to create thread // Give it time to create thread
sleep(1); 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 // Set RX freq and gain
phy.get_radio()->set_rx_freq(prog_args.uhd_freq); phy.get_radio()->set_rx_freq(prog_args.uhd_freq);
phy.get_radio()->set_rx_gain(prog_args.uhd_gain); 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_modem_table_lte(&modulator, modulation, false);
srslte_tcod_t turbocoder; 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_t dft_precod;
srslte_dft_precoding_init(&dft_precod, 12); 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); uint32_t ncoded_bits = sf_n_samples/8/srslte_mod_bits_x_symbol(modulation);
uint8_t *data = malloc(sizeof(uint8_t)*nbits); 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; float rsrp=0.0, rsrq=0.0, snr=0.0;
bool decode_pdsch; bool decode_pdsch;
int pdcch_tx=0; int pdcch_tx=0;
srslte_ra_pdsch_t old_ra_dl; srslte_ra_dl_dci_t old_ra_dl;
bzero(&old_ra_dl, sizeof(srslte_ra_pdsch_t)); bzero(&old_ra_dl, sizeof(srslte_ra_dl_dci_t));
ue_sync.correct_cfo = prog_args.enable_cfo; 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, 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); ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
} }
if (memcmp(&ue_dl.ra_dl, &old_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_pdsch_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); fflush(stdout);printf("\nCFI:\t%d\n", ue_dl.cfi);
printf("Format: %s\n", srslte_dci_format_string(ue_dl.dci_format)); printf("Format: %s\n", srslte_dci_format_string(ue_dl.dci_format));
srslte_ra_pdsch_fprint(stdout, &old_ra_dl, cell.nof_prb); srslte_ra_pdsch_fprint(stdout, &old_ra_dl, cell.nof_prb);

Loading…
Cancel
Save