Added PUCCH Format 1/a/b

master
ismagom 10 years ago
parent 6eb3f1f484
commit 4fed92c21c

@ -0,0 +1,75 @@
clear
ueConfig=struct('NCellID',1,'NULRB',6,'NSubframe',8,'RNTI',68,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[1:4]','Modulation','QPSK','RV',0,'Shortened',0);
addpath('../../debug/lte/phy/lib/phch/test')
% TBs=0:13:211;
% cqilen=[0, 8, 17];
% mods={'QPSK','16QAM','64QAM'};
% rvs=0;
% betas=0:3:11;
TBs=88;
cqilen=0;
mods={'QPSK'};
rvs=0;
betas=0;
for i=1:length(TBs)
for m=1:length(mods)
for r=1:length(rvs)
for bcqi=1:length(betas)
for bri=1:length(betas)
for back=1:length(betas)
for c=1:length(cqilen)
trblkin=randi(2,TBs(i),1)-1;
puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r);
puschConfig.BetaCQI = 2+betas(bcqi);
puschConfig.BetaRI = 2+betas(bri);
puschConfig.BetaACK = 2+betas(back);
if (betas(bri)>0)
ri_bit=randi(2,1,1)-1;
else
ri_bit=[];
end
if (betas(back)>0)
ack_bit=randi(2,1,1)-1;
else
ack_bit=[];
end
if (cqilen(c)>0 || TBs(i)>0)
[cw, info]=lteULSCH(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit,[]);
cw_mat=ltePUSCH(ueConfig,puschConfig,cw);
idx=ltePUSCHIndices(ueConfig,puschConfig);
subframe_mat = lteULResourceGrid(ueConfig);
subframe_mat(idx)=cw_mat;
waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0);
[waveform_lib, subframe_lib, cwlib]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
err=mean(abs(waveform-waveform_lib));
if (err > 10^-6)
disp(err)
error('Error!');
end
end
end
end
end
end
end
end
end
if (length(TBs) == 1)
%disp(info)
%n=1:length(mat);
%plot(abs(double(mat)-double(lib)))
%plot(n,real(lib(n)),n,real(mat(n)))
plot(abs(waveform_lib-waveform))
end

@ -379,16 +379,16 @@ int main(int argc, char **argv) {
srslte_pusch_hopping_cfg_t hop_cfg; srslte_pusch_hopping_cfg_t hop_cfg;
bzero(&hop_cfg, sizeof(srslte_pusch_hopping_cfg_t)); bzero(&hop_cfg, sizeof(srslte_pusch_hopping_cfg_t));
srslte_refsignal_drms_pusch_cfg_t drms_cfg; srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
bzero(&drms_cfg, sizeof(srslte_refsignal_drms_pusch_cfg_t)); bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
drms_cfg.beta_pusch = 1.0; dmrs_cfg.beta_pusch = 1.0;
drms_cfg.group_hopping_en = false; dmrs_cfg.group_hopping_en = false;
drms_cfg.sequence_hopping_en = false; dmrs_cfg.sequence_hopping_en = false;
drms_cfg.delta_ss = 0; dmrs_cfg.delta_ss = 0;
drms_cfg.cyclic_shift = 0; dmrs_cfg.cyclic_shift = 0;
drms_cfg.cyclic_shift_for_drms = 0; dmrs_cfg.cyclic_shift_for_dmrs = 0;
drms_cfg.en_drms_2 = false; dmrs_cfg.en_dmrs_2 = false;
srslte_ue_ul_set_pusch_cfg(&ue_ul, &drms_cfg, &hop_cfg); srslte_ue_ul_set_pusch_cfg(&ue_ul, &dmrs_cfg, &hop_cfg);
cf_t *ul_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); cf_t *ul_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (!ul_signal) { if (!ul_signal) {

@ -219,7 +219,7 @@ int main(int argc, char **argv) {
/* If peak detected */ /* If peak detected */
if (peak_value[N_id_2] > corr_peak_threshold) { if (peak_value[N_id_2] > corr_peak_threshold) {
sss_idx = peak_pos[N_id_2]-2*(symbol_sz+SRSLTE_CP(symbol_sz,SRSLTE_CP_NORM_LEN)); sss_idx = peak_pos[N_id_2]-2*(symbol_sz+SRSLTE_CP_LEN(symbol_sz,SRSLTE_CP_NORM_LEN));
if (sss_idx >= 0) { if (sss_idx >= 0) {
srslte_sss_synch_m0m1_diff(&sss[N_id_2], &input[sss_idx], srslte_sss_synch_m0m1_diff(&sss[N_id_2], &input[sss_idx],
&m0, &m0_value, &m1, &m1_value); &m0, &m0_value, &m1, &m1_value);

@ -47,16 +47,15 @@
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint32_t cyclic_shift; uint32_t cyclic_shift;
uint32_t cyclic_shift_for_drms; uint32_t cyclic_shift_for_dmrs;
uint32_t delta_ss; uint32_t delta_ss;
bool en_drms_2; bool en_dmrs_2;
float beta_pusch; float beta_pusch;
bool group_hopping_en; bool group_hopping_en;
bool sequence_hopping_en; bool sequence_hopping_en;
}srslte_refsignal_drms_pusch_cfg_t; }srslte_refsignal_dmrs_pusch_cfg_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
float beta_pucch;
uint32_t nof_prb; uint32_t nof_prb;
}srslte_refsignal_srs_cfg_t; }srslte_refsignal_srs_cfg_t;
@ -77,28 +76,35 @@ SRSLTE_API int srslte_refsignal_ul_init(srslte_refsignal_ul_t *q,
SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q); SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q);
SRSLTE_API bool srslte_refsignal_drms_pusch_cfg_isvalid(srslte_refsignal_ul_t *q, SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float *arg,
srslte_refsignal_drms_pusch_cfg_t *cfg, uint32_t u);
SRSLTE_API bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *cfg,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API void srslte_refsignal_drms_pusch_put(srslte_refsignal_ul_t *q, SRSLTE_API int srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t *q,
srslte_refsignal_drms_pusch_cfg_t *cfg, srslte_refsignal_dmrs_pusch_cfg_t *cfg,
uint32_t nof_prb,
uint32_t sf_idx,
cf_t *r_pusch);
SRSLTE_API void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *cfg,
cf_t *r_pusch, cf_t *r_pusch,
uint32_t nof_prb, uint32_t nof_prb,
uint32_t n_prb[2], uint32_t n_prb[2],
cf_t *sf_symbols); cf_t *sf_symbols);
SRSLTE_API int srslte_refsignal_dmrs_gen(srslte_refsignal_ul_t *q,
srslte_refsignal_drms_pusch_cfg_t *cfg,
uint32_t nof_prb,
uint32_t sf_idx,
cf_t *r_pusch);
SRSLTE_API int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, SRSLTE_API int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q,
srslte_pucch_cfg_t *cfg, srslte_pucch_cfg_t *cfg,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t n_rb, cf_t *r_pucch);
cf_t *r_pucch) ;
SRSLTE_API int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q,
srslte_pucch_cfg_t* cfg,
cf_t *r_pucch,
cf_t *output);
SRSLTE_API void srslte_refsignal_srs_gen(srslte_refsignal_ul_t *q, SRSLTE_API void srslte_refsignal_srs_gen(srslte_refsignal_ul_t *q,
srslte_refsignal_srs_cfg_t *cfg, srslte_refsignal_srs_cfg_t *cfg,

@ -91,9 +91,9 @@ typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t;
#define SRSLTE_CP_ISEXT(cp) (cp==SRSLTE_CP_EXT) #define SRSLTE_CP_ISEXT(cp) (cp==SRSLTE_CP_EXT)
#define SRSLTE_CP_NSYMB(cp) (SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB) #define SRSLTE_CP_NSYMB(cp) (SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB)
#define SRSLTE_CP(symbol_sz, c) ((int) ceil((((float) (c)*(symbol_sz))/2048))) #define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceil((((float) (c)*(symbol_sz))/2048)))
#define SRSLTE_CP_NORM(symbol, symbol_sz) ((symbol==0)?SRSLTE_CP((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP((symbol_sz),SRSLTE_CP_NORM_LEN)) #define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) ((symbol==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN))
#define SRSLTE_CP_EXT(symbol_sz) (SRSLTE_CP((symbol_sz),SRSLTE_CP_EXT_LEN)) #define SRSLTE_CP_LEN_EXT(symbol_sz) (SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_EXT_LEN))
#define SRSLTE_SLOT_LEN(symbol_sz) (480*((symbol_sz)/64)) #define SRSLTE_SLOT_LEN(symbol_sz) (480*((symbol_sz)/64))
#define SRSLTE_SF_LEN(symbol_sz) (2*SRSLTE_SLOT_LEN(symbol_sz)) #define SRSLTE_SF_LEN(symbol_sz) (2*SRSLTE_SLOT_LEN(symbol_sz))
@ -109,8 +109,8 @@ typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t;
#define SRSLTE_LTE_TS 1.0/(15000.0*2048) #define SRSLTE_LTE_TS 1.0/(15000.0*2048)
#define SRSLTE_SLOT_IDX_CPNORM(symbol_idx, symbol_sz) (symbol_idx==0?0:(symbol_sz + SRSLTE_CP(symbol_sz, SRSLTE_CP_NORM_0_LEN) + \ #define SRSLTE_SLOT_IDX_CPNORM(symbol_idx, symbol_sz) (symbol_idx==0?0:(symbol_sz + SRSLTE_CP_LEN(symbol_sz, SRSLTE_CP_NORM_0_LEN) + \
(symbol_idx-1)*(symbol_sz+SRSLTE_CP(symbol_sz, SRSLTE_CP_NORM_LEN)))) (symbol_idx-1)*(symbol_sz+SRSLTE_CP_LEN(symbol_sz, SRSLTE_CP_NORM_LEN))))
#define SRSLTE_SLOT_IDX_CPEXT(idx, symbol_sz) (idx*(symbol_sz+SRSLTE_CP(symbol_sz, SRSLTE_CP_EXT_LEN))) #define SRSLTE_SLOT_IDX_CPEXT(idx, symbol_sz) (idx*(symbol_sz+SRSLTE_CP(symbol_sz, SRSLTE_CP_EXT_LEN)))
#define SRSLTE_RE_IDX(nof_prb, symbol_idx, sample_idx) ((symbol_idx)*(nof_prb)*(SRSLTE_NRE) + sample_idx) #define SRSLTE_RE_IDX(nof_prb, symbol_idx, sample_idx) ((symbol_idx)*(nof_prb)*(SRSLTE_NRE) + sample_idx)
@ -213,6 +213,9 @@ SRSLTE_API uint32_t srslte_voffset(uint32_t symbol_id,
uint32_t cell_id, uint32_t cell_id,
uint32_t nof_ports); uint32_t nof_ports);
SRSLTE_API int srslte_group_hopping_f_gh(uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME],
uint32_t cell_id);
SRSLTE_API uint32_t srslte_N_ta_new_rar(uint32_t ta); 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,

@ -38,15 +38,6 @@
#include "srslte/config.h" #include "srslte/config.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/mimo/precoding.h"
#include "srslte/mimo/layermap.h"
#include "srslte/modem/mod.h"
#include "srslte/modem/demod_soft.h"
#include "srslte/scrambling/scrambling.h"
#include "srslte/phch/regs.h"
#include "srslte/phch/sch.h"
#include "srslte/phch/harq.h"
#include "srslte/dft/dft_precoding.h"
#define SRSLTE_PUCCH_N_SEQ 12 // Only Format 1, 1a and 1b supported #define SRSLTE_PUCCH_N_SEQ 12 // Only Format 1, 1a and 1b supported
#define SRSLTE_PUCCH_MAX_BITS 2 #define SRSLTE_PUCCH_MAX_BITS 2
@ -66,7 +57,9 @@ typedef struct SRSLTE_API {
float beta_pucch; float beta_pucch;
uint32_t delta_pucch_shift; uint32_t delta_pucch_shift;
uint32_t n_pucch; uint32_t n_pucch;
uint32_t n_rb_2;
uint32_t N_cs; uint32_t N_cs;
bool group_hopping_en;
} srslte_pucch_cfg_t; } srslte_pucch_cfg_t;
/* PUSCH object */ /* PUSCH object */
@ -75,8 +68,9 @@ typedef struct SRSLTE_API {
srslte_pucch_cfg_t pucch_cfg; srslte_pucch_cfg_t pucch_cfg;
uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]; uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB];
float tmp_arg[SRSLTE_PUCCH_N_SF_MAX*SRSLTE_PUCCH_N_SEQ]; uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME];
float y[SRSLTE_PUCCH_N_SEQ]; float tmp_arg[SRSLTE_PUCCH_N_SEQ];
float z[SRSLTE_PUCCH_N_SF_MAX*SRSLTE_PUCCH_N_SEQ];
}srslte_pucch_t; }srslte_pucch_t;
@ -93,20 +87,26 @@ SRSLTE_API int srslte_pucch_set_rnti(srslte_pucch_t *q,
SRSLTE_API int srslte_pucch_encode(srslte_pucch_t *q, SRSLTE_API int srslte_pucch_encode(srslte_pucch_t *q,
srslte_pucch_cfg_t *cfg, srslte_pucch_cfg_t *cfg,
uint32_t sf_idx,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint8_t bits[SRSLTE_PUCCH_MAX_BITS],
cf_t *sf_symbols); cf_t *sf_symbols);
SRSLTE_API float srslte_pucch_get_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB], SRSLTE_API float srslte_pucch_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
srslte_pucch_cfg_t *cfg, srslte_pucch_cfg_t *cfg,
srslte_cp_t cp, srslte_cp_t cp,
bool is_drms, bool is_dmrs,
uint32_t ns, uint32_t ns,
uint32_t l, uint32_t l,
uint32_t *n_oc); uint32_t *n_oc,
uint32_t *n_prime_ns);
SRSLTE_API int srslte_generate_n_cs_cell(srslte_cell_t cell, SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg,
srslte_cp_t cp);
SRSLTE_API int srslte_pucch_n_cs_cell(srslte_cell_t cell,
uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]); uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]);
SRSLTE_API bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg); SRSLTE_API bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg);
#endif #endif

@ -94,6 +94,7 @@
#include "srslte/phch/pdsch.h" #include "srslte/phch/pdsch.h"
#include "srslte/phch/phich.h" #include "srslte/phch/phich.h"
#include "srslte/phch/pusch.h" #include "srslte/phch/pusch.h"
#include "srslte/phch/pucch.h"
#include "srslte/phch/prach.h" #include "srslte/phch/prach.h"
#include "srslte/phch/ra.h" #include "srslte/phch/ra.h"
#include "srslte/phch/regs.h" #include "srslte/phch/regs.h"

@ -63,9 +63,9 @@ typedef struct SRSLTE_API {
float current_cfo; float current_cfo;
srslte_refsignal_drms_pusch_cfg_t drms_cfg; srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
srslte_refsignal_ul_t drms; srslte_refsignal_ul_t dmrs;
srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES]; srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES];
srslte_pusch_t pusch; srslte_pusch_t pusch;
@ -91,7 +91,7 @@ SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q,
bool enabled); bool enabled);
SRSLTE_API void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q, SRSLTE_API void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q,
srslte_refsignal_drms_pusch_cfg_t *drms_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_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,

@ -39,11 +39,11 @@
#include "ul_rs_tables.h" #include "ul_rs_tables.h"
// n_drms_2 table 5.5.2.1.1-1 from 36.211 // n_dmrs_2 table 5.5.2.1.1-1 from 36.211
uint32_t n_drms_2[8] = { 0, 6, 3, 4, 2, 8, 10, 9 }; uint32_t n_dmrs_2[8] = { 0, 6, 3, 4, 2, 8, 10, 9 };
// n_drms_1 table 5.5.2.1.1-2 from 36.211 // n_dmrs_1 table 5.5.2.1.1-2 from 36.211
uint32_t n_drms_1[8] = { 0, 2, 3, 4, 6, 8, 9, 10 }; uint32_t n_dmrs_1[8] = { 0, 2, 3, 4, 6, 8, 9, 10 };
/* Orthogonal sequences for PUCCH formats 1a, 1b and 1c. Table 5.5.2.2.1-2 /* Orthogonal sequences for PUCCH formats 1a, 1b and 1c. Table 5.5.2.2.1-2
*/ */
@ -58,10 +58,10 @@ float w_arg_pucch_format1_cpext[3][2] = {{0, 0},
float w_arg_pucch_format2_cpnorm[2] = {0, 0}; float w_arg_pucch_format2_cpnorm[2] = {0, 0};
float w_arg_pucch_format2_cpext[1] = {0}; float w_arg_pucch_format2_cpext[1] = {0};
uint32_t pucch_symbol_format1_cpnorm[3] = {2, 3, 5}; uint32_t pucch_dmrs_symbol_format1_cpnorm[3] = {2, 3, 4};
uint32_t pucch_symbol_format1_cpext[2] = {2, 3}; uint32_t pucch_dmrs_symbol_format1_cpext[2] = {2, 3};
uint32_t pucch_symbol_format2_cpnorm[2] = {1, 5}; uint32_t pucch_dmrs_symbol_format2_cpnorm[2] = {1, 5};
uint32_t pucch_symbol_format2_cpext[1] = {3}; uint32_t pucch_dmrs_symbol_format2_cpext[1] = {3};
/** Computes n_prs values used to compute alpha as defined in 5.5.2.1.1 of 36.211 */ /** Computes n_prs values used to compute alpha as defined in 5.5.2.1.1 of 36.211 */
static int generate_n_prs(srslte_refsignal_ul_t * q) { static int generate_n_prs(srslte_refsignal_ul_t * q) {
@ -89,25 +89,10 @@ static int generate_n_prs(srslte_refsignal_ul_t * q) {
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
/** Computes sequence-group pattern f_gh according to 5.5.1.3 of 36.211 */ void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u) {
static int generate_group_hopping_f_gh(srslte_refsignal_ul_t *q) { for (int i = 0; i < SRSLTE_NRE; i++) {
srslte_sequence_t seq; arg[i] = phi_M_sc_12[u][i] * M_PI / 4;
bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_LTE_pr(&seq, 160, q->cell.id / 30)) {
return SRSLTE_ERROR;
}
for (uint32_t ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
uint32_t f_gh = 0;
for (int i = 0; i < 8; i++) {
f_gh += (((uint32_t) seq.c[8 * ns + i]) << i);
}
q->f_gh[ns] = f_gh;
} }
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS;
} }
static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) { static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
@ -153,7 +138,7 @@ int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell)
} }
// Precompute group hopping values u. // Precompute group hopping values u.
if (generate_group_hopping_f_gh(q)) { if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
goto free_and_exit; goto free_and_exit;
} }
@ -162,7 +147,7 @@ int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell)
goto free_and_exit; goto free_and_exit;
} }
if (srslte_generate_n_cs_cell(q->cell, q->n_cs_cell)) { if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
goto free_and_exit; goto free_and_exit;
} }
@ -193,12 +178,6 @@ uint32_t largest_prime_lower_than(uint32_t x) {
return 0; return 0;
} }
static void arg_r_uv_1prb(float *arg, uint32_t u) {
for (int i = 0; i < SRSLTE_NRE; i++) {
arg[i] = phi_M_sc_12[u][i] * M_PI / 4;
}
}
static void arg_r_uv_2prb(float *arg, uint32_t u) { static void arg_r_uv_2prb(float *arg, uint32_t u) {
for (int i = 0; i < 2*SRSLTE_NRE; i++) { for (int i = 0; i < 2*SRSLTE_NRE; i++) {
arg[i] = phi_M_sc_24[u][i] * M_PI / 4; arg[i] = phi_M_sc_24[u][i] * M_PI / 4;
@ -232,9 +211,9 @@ static void arg_r_uv_mprb(float *arg, uint32_t M_sc, uint32_t u, uint32_t v) {
} }
/* Computes argument of r_u_v signal */ /* Computes argument of r_u_v signal */
static void compute_pusch_r_uv_arg(srslte_refsignal_ul_t *q, srslte_refsignal_drms_pusch_cfg_t *cfg, uint32_t nof_prb, uint32_t u, uint32_t v) { static void compute_pusch_r_uv_arg(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg, uint32_t nof_prb, uint32_t u, uint32_t v) {
if (nof_prb == 1) { if (nof_prb == 1) {
arg_r_uv_1prb(q->tmp_arg, u); srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u);
} else if (nof_prb == 2) { } else if (nof_prb == 2) {
arg_r_uv_2prb(q->tmp_arg, u); arg_r_uv_2prb(q->tmp_arg, u);
} else { } else {
@ -243,20 +222,20 @@ static void compute_pusch_r_uv_arg(srslte_refsignal_ul_t *q, srslte_refsignal_dr
} }
/* Calculates alpha according to 5.5.2.1.1 of 36.211 */ /* Calculates alpha according to 5.5.2.1.1 of 36.211 */
static float get_alpha(srslte_refsignal_ul_t *q, srslte_refsignal_drms_pusch_cfg_t *cfg, uint32_t ns) { static float pusch_alpha(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg, uint32_t ns) {
uint32_t n_drms_2_val = 0; uint32_t n_dmrs_2_val = 0;
if (cfg->en_drms_2) { if (cfg->en_dmrs_2) {
n_drms_2_val = n_drms_2[cfg->cyclic_shift_for_drms]; n_dmrs_2_val = n_dmrs_2[cfg->cyclic_shift_for_dmrs];
} }
uint32_t n_cs = (n_drms_1[cfg->cyclic_shift] + n_drms_2_val + q->n_prs_pusch[cfg->delta_ss][ns]) % 12; uint32_t n_cs = (n_dmrs_1[cfg->cyclic_shift] + n_dmrs_2_val + q->n_prs_pusch[cfg->delta_ss][ns]) % 12;
return 2 * M_PI * (n_cs) / 12; return 2 * M_PI * (n_cs) / 12;
} }
bool srslte_refsignal_drms_pusch_cfg_isvalid(srslte_refsignal_ul_t *q, srslte_refsignal_drms_pusch_cfg_t *cfg, uint32_t nof_prb) { bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg, uint32_t nof_prb) {
if (cfg->cyclic_shift < SRSLTE_NOF_CSHIFT && if (cfg->cyclic_shift < SRSLTE_NOF_CSHIFT &&
cfg->cyclic_shift_for_drms < SRSLTE_NOF_CSHIFT && cfg->cyclic_shift_for_dmrs < SRSLTE_NOF_CSHIFT &&
cfg->delta_ss < SRSLTE_NOF_DELTA_SS && cfg->delta_ss < SRSLTE_NOF_DELTA_SS &&
nof_prb < q->cell.nof_prb) { nof_prb < q->cell.nof_prb) {
return true; return true;
@ -265,7 +244,7 @@ bool srslte_refsignal_drms_pusch_cfg_isvalid(srslte_refsignal_ul_t *q, srslte_re
} }
} }
void srslte_refsignal_drms_pusch_put(srslte_refsignal_ul_t *q, srslte_refsignal_drms_pusch_cfg_t *cfg, void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg,
cf_t *r_pusch, cf_t *r_pusch,
uint32_t nof_prb, uint32_t nof_prb,
uint32_t n_prb[2], uint32_t n_prb[2],
@ -280,11 +259,11 @@ void srslte_refsignal_drms_pusch_put(srslte_refsignal_ul_t *q, srslte_refsignal_
} }
/* Generate DRMS for PUSCH signal according to 5.5.2.1 of 36.211 */ /* Generate DRMS for PUSCH signal according to 5.5.2.1 of 36.211 */
int srslte_refsignal_dmrs_gen(srslte_refsignal_ul_t *q, srslte_refsignal_drms_pusch_cfg_t *cfg, uint32_t nof_prb, uint32_t sf_idx, cf_t *r_pusch) int srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg, uint32_t nof_prb, uint32_t sf_idx, cf_t *r_pusch)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (srslte_refsignal_drms_pusch_cfg_isvalid(q, cfg, nof_prb)) { if (srslte_refsignal_dmrs_pusch_cfg_isvalid(q, cfg, nof_prb)) {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) { for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
@ -305,7 +284,7 @@ int srslte_refsignal_dmrs_gen(srslte_refsignal_ul_t *q, srslte_refsignal_drms_pu
compute_pusch_r_uv_arg(q, cfg, nof_prb, u, v); compute_pusch_r_uv_arg(q, cfg, nof_prb, u, v);
// Add cyclic prefix alpha // Add cyclic prefix alpha
float alpha = get_alpha(q, cfg, ns); float alpha = pusch_alpha(q, cfg, ns);
if (srslte_verbose == SRSLTE_VERBOSE_DEBUG) { if (srslte_verbose == SRSLTE_VERBOSE_DEBUG) {
uint32_t N_sz = largest_prime_lower_than(nof_prb*SRSLTE_NRE); uint32_t N_sz = largest_prime_lower_than(nof_prb*SRSLTE_NRE);
@ -324,50 +303,89 @@ int srslte_refsignal_dmrs_gen(srslte_refsignal_ul_t *q, srslte_refsignal_drms_pu
return ret; return ret;
} }
int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t *cfg, uint32_t sf_idx, uint32_t n_rb, cf_t *r_pucch) /* Number of PUCCH demodulation reference symbols per slot N_rs_pucch tABLE 5.5.2.2.1-1 36.211 */
{ static uint32_t get_N_rs(srslte_pucch_format_t format, srslte_cp_t cp) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; switch (format) {
if (srslte_pucch_cfg_isvalid(cfg)) { case SRSLTE_PUCCH_FORMAT_1:
ret = SRSLTE_ERROR; case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B:
if (SRSLTE_CP_ISNORM(cp)) {
return 3;
} else {
return 2;
}
case SRSLTE_PUCCH_FORMAT_2:
if (SRSLTE_CP_ISNORM(cp)) {
return 2;
} else {
return 1;
}
case SRSLTE_PUCCH_FORMAT_2A:
case SRSLTE_PUCCH_FORMAT_2B:
return 2;
}
return 0;
}
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) { /* Table 5.5.2.2.2-1: Demodulation reference signal location for different PUCCH formats. 36.211 */
uint32_t N_rs=0; static uint32_t get_pucch_dmrs_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp) {
uint32_t *pucch_symbol = NULL; switch (format) {
switch (cfg->format) {
case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_1:
case SRSLTE_PUCCH_FORMAT_1A: case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B: case SRSLTE_PUCCH_FORMAT_1B:
if (SRSLTE_CP_ISNORM(q->cell.cp)) { if (SRSLTE_CP_ISNORM(cp)) {
N_rs = 3; if (m < 4) {
pucch_symbol=pucch_symbol_format1_cpnorm; return pucch_dmrs_symbol_format1_cpnorm[m];
}
} else { } else {
N_rs=2; if (m < 3) {
pucch_symbol=pucch_symbol_format1_cpext; return pucch_dmrs_symbol_format1_cpext[m];
}
} }
break;
case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2:
if (SRSLTE_CP_ISNORM(q->cell.cp)) { if (SRSLTE_CP_ISNORM(cp)) {
N_rs = 2; if (m < 3) {
pucch_symbol=pucch_symbol_format2_cpnorm; return pucch_dmrs_symbol_format2_cpnorm[m];
}
} else { } else {
N_rs=1; if (m < 2) {
pucch_symbol=pucch_symbol_format2_cpext; return pucch_dmrs_symbol_format2_cpext[m];
}
} }
break;
case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2A:
case SRSLTE_PUCCH_FORMAT_2B: case SRSLTE_PUCCH_FORMAT_2B:
N_rs = 2; if (m < 3) {
pucch_symbol=pucch_symbol_format2_cpnorm; return pucch_dmrs_symbol_format2_cpnorm[m];
break; }
}
return 0;
}
/* Generates DMRS for PUCCH according to 5.5.2.2 in 36.211 */
int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t *cfg, uint32_t sf_idx, cf_t *r_pucch)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (srslte_pucch_cfg_isvalid(cfg)) {
ret = SRSLTE_ERROR;
uint32_t N_rs=get_N_rs(cfg->format, q->cell.cp);
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
// Get group hopping number u
uint32_t f_gh=0;
if (cfg->group_hopping_en) {
f_gh = q->f_gh[ns];
} }
uint32_t u = (f_gh + (q->cell.id%30))%30;
srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u);
if (pucch_symbol) {
for (uint32_t m=0;m<N_rs;m++) { for (uint32_t m=0;m<N_rs;m++) {
uint32_t n_oc=0; uint32_t n_oc=0;
uint32_t l = pucch_symbol[m]; uint32_t l = get_pucch_dmrs_symbol(m, cfg->format, q->cell.cp);
// Add cyclic prefix alpha // Add cyclic prefix alpha
float alpha = srslte_pucch_get_alpha(q->n_cs_cell, cfg, q->cell.cp, true, ns, l, &n_oc); float alpha = srslte_pucch_alpha(q->n_cs_cell, cfg, q->cell.cp, true, ns, l, &n_oc, NULL);
// Choose number of symbols and orthogonal sequence from Tables 5.5.2.2.1-1 to -3 // Choose number of symbols and orthogonal sequence from Tables 5.5.2.2.1-1 to -3
float *w=NULL; float *w=NULL;
@ -395,17 +413,45 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t
} }
if (w) { if (w) {
for (uint32_t n=0;n<SRSLTE_NRE*n_rb;n++) { for (uint32_t n=0;n<SRSLTE_NRE;n++) {
r_pucch[(ns%2)*SRSLTE_NRE*n_rb*N_rs+m*SRSLTE_NRE*n_rb+n] = cfg->beta_pucch*cexpf(I*(w[m]+q->tmp_arg[n]+alpha*n)); r_pucch[(ns%2)*SRSLTE_NRE*N_rs+m*SRSLTE_NRE+n] = cfg->beta_pucch*w[m]*cexpf(I*(q->tmp_arg[n]+alpha*n));
} }
} else { } else {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }
} else {
return SRSLTE_ERROR;
} }
ret = SRSLTE_SUCCESS;
}
return ret;
}
/* Maps PUCCH DMRS to the physical resources as defined in 5.5.2.2.2 in 36.211 */
int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t *cfg, cf_t *r_pucch, cf_t *output)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q && cfg && output) {
ret = SRSLTE_ERROR;
// Determine m
uint32_t m = srslte_pucch_m(cfg, q->cell.cp);
uint32_t N_rs = get_N_rs(cfg->format, q->cell.cp);
for (uint32_t ns=0;ns<2;ns++) {
// Determine n_prb
uint32_t n_prb = m/2;
if ((m+ns)%2) {
n_prb = q->cell.nof_prb-1-m/2;
}
for (uint32_t i=0;i<N_rs;i++) {
uint32_t l = get_pucch_dmrs_symbol(m, cfg->format, q->cell.cp);
memcpy(&output[SRSLTE_RE_IDX(q->cell.nof_prb, l, n_prb*SRSLTE_NRE)],
&r_pucch[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE],
SRSLTE_NRE*sizeof(cf_t));
} }
}
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }
return ret; return ret;

@ -49,7 +49,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ {
srslte_cell_t cell; srslte_cell_t cell;
srslte_refsignal_ul_t refs; srslte_refsignal_ul_t refs;
srslte_refsignal_drms_pusch_cfg_t pusch_cfg; srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
uint32_t sf_idx; uint32_t sf_idx;
if (nrhs != NOF_INPUTS) { if (nrhs != NOF_INPUTS) {
@ -73,7 +73,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
bzero(&pusch_cfg, sizeof(srslte_refsignal_drms_pusch_cfg_t)); bzero(&pusch_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
pusch_cfg.group_hopping_en = false; pusch_cfg.group_hopping_en = false;
@ -104,11 +104,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
uint32_t nof_prb = mexutils_read_f(p, &prbset); uint32_t nof_prb = mexutils_read_f(p, &prbset);
if (mexutils_read_uint32_struct(PUSCHCFG, "DynCyclicShift", &pusch_cfg.cyclic_shift_for_drms)) { if (mexutils_read_uint32_struct(PUSCHCFG, "DynCyclicShift", &pusch_cfg.cyclic_shift_for_dmrs)) {
pusch_cfg.cyclic_shift_for_drms = 0; pusch_cfg.cyclic_shift_for_dmrs = 0;
pusch_cfg.en_drms_2 = false; pusch_cfg.en_dmrs_2 = false;
} else { } else {
pusch_cfg.en_drms_2 = true; pusch_cfg.en_dmrs_2 = true;
} }
pusch_cfg.beta_pusch = 1.0; pusch_cfg.beta_pusch = 1.0;
@ -120,7 +120,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexPrintf("nof_prb: %d, ",nof_prb); mexPrintf("nof_prb: %d, ",nof_prb);
mexPrintf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift); mexPrintf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift);
mexPrintf("cyclic_shift_for_drms: %d, ",pusch_cfg.cyclic_shift_for_drms); mexPrintf("cyclic_shift_for_dmrs: %d, ",pusch_cfg.cyclic_shift_for_dmrs);
mexPrintf("delta_ss: %d, ",pusch_cfg.delta_ss); mexPrintf("delta_ss: %d, ",pusch_cfg.delta_ss);
cf_t *signal = srslte_vec_malloc(2*SRSLTE_NRE*nof_prb*sizeof(cf_t)); cf_t *signal = srslte_vec_malloc(2*SRSLTE_NRE*nof_prb*sizeof(cf_t));
@ -135,11 +135,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t)); bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t));
//mexPrintf("Generating DRMS for ns=%d, nof_prb=%d\n", 2*sf_idx+i,pusch_cfg.nof_prb); //mexPrintf("Generating DRMS for ns=%d, nof_prb=%d\n", 2*sf_idx+i,pusch_cfg.nof_prb);
srslte_refsignal_dmrs_gen(&refs, &pusch_cfg, nof_prb, sf_idx, signal); srslte_refsignal_dmrs_pusch_gen(&refs, &pusch_cfg, nof_prb, sf_idx, signal);
uint32_t n_prb[2]; uint32_t n_prb[2];
n_prb[0] = prbset[0]; n_prb[0] = prbset[0];
n_prb[1] = prbset[0]; n_prb[1] = prbset[0];
srslte_refsignal_drms_pusch_put(&refs, &pusch_cfg, signal, nof_prb, n_prb, sf_symbols); srslte_refsignal_dmrs_pusch_put(&refs, &pusch_cfg, signal, nof_prb, n_prb, sf_symbols);
if (nlhs >= 1) { if (nlhs >= 1) {
mexutils_write_cf(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1); mexutils_write_cf(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
} }

@ -76,7 +76,7 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
srslte_refsignal_ul_t refs; srslte_refsignal_ul_t refs;
srslte_refsignal_drms_pusch_cfg_t pusch_cfg; srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
cf_t *signal = NULL; cf_t *signal = NULL;
int ret = -1; int ret = -1;
@ -100,11 +100,11 @@ int main(int argc, char **argv) {
for (int cshift=0;cshift<SRSLTE_NOF_CSHIFT;cshift++) { for (int cshift=0;cshift<SRSLTE_NOF_CSHIFT;cshift++) {
for (int h=0;h<3;h++) { for (int h=0;h<3;h++) {
for (int sf_idx=0;sf_idx<SRSLTE_NSLOTS_X_FRAME;sf_idx++) { for (int sf_idx=0;sf_idx<SRSLTE_NSLOTS_X_FRAME;sf_idx++) {
for (int cshift_drms=0;cshift_drms<SRSLTE_NOF_CSHIFT;cshift_drms++) { for (int cshift_dmrs=0;cshift_dmrs<SRSLTE_NOF_CSHIFT;cshift_dmrs++) {
pusch_cfg.beta_pusch = 1.0; pusch_cfg.beta_pusch = 1.0;
uint32_t nof_prb = n; uint32_t nof_prb = n;
pusch_cfg.cyclic_shift = cshift; pusch_cfg.cyclic_shift = cshift;
pusch_cfg.cyclic_shift_for_drms = cshift_drms; pusch_cfg.cyclic_shift_for_dmrs = cshift_dmrs;
pusch_cfg.delta_ss = delta_ss; pusch_cfg.delta_ss = delta_ss;
if (!h) { if (!h) {
pusch_cfg.group_hopping_en = false; pusch_cfg.group_hopping_en = false;
@ -116,14 +116,14 @@ int main(int argc, char **argv) {
pusch_cfg.group_hopping_en = true; pusch_cfg.group_hopping_en = true;
pusch_cfg.sequence_hopping_en = false; pusch_cfg.sequence_hopping_en = false;
} }
pusch_cfg.en_drms_2 = true; pusch_cfg.en_dmrs_2 = true;
printf("Beta: %f, ",pusch_cfg.beta_pusch); printf("Beta: %f, ",pusch_cfg.beta_pusch);
printf("nof_prb: %d, ",nof_prb); printf("nof_prb: %d, ",nof_prb);
printf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift); printf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift);
printf("cyclic_shift_for_drms: %d, ",pusch_cfg.cyclic_shift_for_drms); printf("cyclic_shift_for_dmrs: %d, ",pusch_cfg.cyclic_shift_for_dmrs);
printf("delta_ss: %d, ",pusch_cfg.delta_ss); printf("delta_ss: %d, ",pusch_cfg.delta_ss);
printf("SF_idx: %d\n", sf_idx); printf("SF_idx: %d\n", sf_idx);
srslte_refsignal_dmrs_gen(&refs, &pusch_cfg, nof_prb, sf_idx, signal); srslte_refsignal_dmrs_pusch_gen(&refs, &pusch_cfg, nof_prb, sf_idx, signal);
exit(0); exit(0);
} }
} }

@ -33,6 +33,7 @@
#include <string.h> #include <string.h>
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/common/sequence.h"
const uint32_t tc_cb_sizes[SRSLTE_NOF_TC_CB_SIZES] = { 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 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, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232,
@ -283,6 +284,27 @@ uint32_t srslte_voffset(uint32_t symbol_id, uint32_t cell_id, uint32_t nof_ports
} }
} }
/** Computes sequence-group pattern f_gh according to 5.5.1.3 of 36.211 */
int srslte_group_hopping_f_gh(uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME], uint32_t cell_id) {
srslte_sequence_t seq;
bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_LTE_pr(&seq, 160, cell_id / 30)) {
return SRSLTE_ERROR;
}
for (uint32_t ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
f_gh[ns] = 0;
for (int i = 0; i < 8; i++) {
f_gh[ns] += (((uint32_t) seq.c[8 * ns + i]) << i);
}
}
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS;
}
/* Returns the number of available RE per PRB */ /* Returns the number of available RE per PRB */
uint32_t srslte_re_x_prb(uint32_t ns, uint32_t symbol, uint32_t nof_ports, uint32_t nof_symbols) { uint32_t srslte_re_x_prb(uint32_t ns, uint32_t symbol, uint32_t nof_ports, uint32_t nof_symbols) {
if (symbol == 0) { if (symbol == 0) {

@ -123,7 +123,7 @@ int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) {
cf_t *ptr = q->shift_buffer; cf_t *ptr = q->shift_buffer;
for (uint32_t n=0;n<2;n++) { for (uint32_t n=0;n<2;n++) {
for (uint32_t i=0;i<q->nof_symbols;i++) { for (uint32_t i=0;i<q->nof_symbols;i++) {
uint32_t cplen = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_NORM(i, q->symbol_sz):SRSLTE_CP_EXT(q->symbol_sz); uint32_t cplen = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
for (uint32_t t=0;t<q->symbol_sz+cplen;t++) { for (uint32_t t=0;t<q->symbol_sz+cplen;t++) {
ptr[t] = cexpf(I*2*M_PI*((float) t-(float)cplen)*freq_shift/q->symbol_sz); ptr[t] = cexpf(I*2*M_PI*((float) t-(float)cplen)*freq_shift/q->symbol_sz);
} }
@ -149,7 +149,7 @@ void srslte_ofdm_tx_free(srslte_ofdm_t *q) {
void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
uint32_t i; uint32_t i;
for (i=0;i<q->nof_symbols;i++) { for (i=0;i<q->nof_symbols;i++) {
input += SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_NORM(i, q->symbol_sz):SRSLTE_CP_EXT(q->symbol_sz); input += SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
srslte_dft_run_c(&q->fft_plan, input, q->tmp); srslte_dft_run_c(&q->fft_plan, input, q->tmp);
memcpy(output, &q->tmp[q->nof_guards], q->nof_re * sizeof(cf_t)); memcpy(output, &q->tmp[q->nof_guards], q->nof_re * sizeof(cf_t));
input += q->symbol_sz; input += q->symbol_sz;
@ -173,7 +173,7 @@ void srslte_ofdm_rx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
uint32_t i, cp_len; uint32_t i, cp_len;
for (i=0;i<q->nof_symbols;i++) { for (i=0;i<q->nof_symbols;i++) {
cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_NORM(i, q->symbol_sz):SRSLTE_CP_EXT(q->symbol_sz); cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t));
srslte_dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]); srslte_dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]);
input += q->nof_re; input += q->nof_re;

@ -33,24 +33,98 @@
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <complex.h>
#include "srslte/phch/pucch.h" #include "srslte/phch/pucch.h"
#include "srslte/phch/uci.h" #include "srslte/common/sequence.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/utils/bit.h"
#include "srslte/utils/debug.h" #include "srslte/utils/debug.h"
#include "srslte/utils/vector.h" #include "srslte/utils/vector.h"
#include "srslte/dft/dft_precoding.h"
#define MAX_PUSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12) #define MAX_PUSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
uint32_t pucch_symbol_format1_cpnorm[4] = {0, 1, 5, 6};
uint32_t pucch_symbol_format1_cpext[4] = {0, 1, 4, 5};
uint32_t pucch_symbol_format2_cpnorm[5] = {0, 2, 3, 4, 6};
uint32_t pucch_symbol_format2_cpext[5] = {0, 1, 2, 4, 5};
// Table 5.4.1-2 Orthogonal sequences w for N_sf=4
float w_n_oc[3][4] = {{1, 1, 1, 1},
{1,-1, 1,-1},
{1,-1,-1,1}};
bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg) { bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg) {
return true; return true;
} }
uint32_t get_N_sf(srslte_pucch_format_t format) {
switch (format) {
case SRSLTE_PUCCH_FORMAT_1:
case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B:
return 4;
case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_2A:
case SRSLTE_PUCCH_FORMAT_2B:
return 5;
}
return 0;
}
uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp) {
switch (format) {
case SRSLTE_PUCCH_FORMAT_1:
case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B:
if (m < 5) {
if (SRSLTE_CP_ISNORM(cp)) {
return pucch_symbol_format1_cpnorm[m];
} else {
return pucch_symbol_format1_cpext[m];
}
}
break;
case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_2A:
case SRSLTE_PUCCH_FORMAT_2B:
if (m < 6) {
if (SRSLTE_CP_ISNORM(cp)) {
return pucch_symbol_format2_cpnorm[m];
} else {
return pucch_symbol_format2_cpext[m];
}
}
break;
}
return 0;
}
// Compute m according to Section 5.4.3 of 36.211
uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg, srslte_cp_t cp) {
uint32_t m=0;
switch (cfg->format) {
case SRSLTE_PUCCH_FORMAT_1:
case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B:
m = cfg->n_rb_2;
uint32_t c=SRSLTE_CP_ISNORM(cp)?3:2;
if (cfg->n_pucch >= c*cfg->N_cs/cfg->delta_pucch_shift) {
m = (cfg->n_pucch-c*cfg->N_cs/cfg->delta_pucch_shift)/(c*SRSLTE_NRE/cfg->delta_pucch_shift)
+cfg->n_rb_2+(cfg->N_cs-1)/8+1;
}
break;
case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_2A:
case SRSLTE_PUCCH_FORMAT_2B:
m = cfg->n_pucch/SRSLTE_NRE;
break;
}
return m;
}
/* Generates n_cs_cell according to Sec 5.4 of 36.211 */ /* Generates n_cs_cell according to Sec 5.4 of 36.211 */
int srslte_generate_n_cs_cell(srslte_cell_t cell, uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]) int srslte_pucch_n_cs_cell(srslte_cell_t cell, uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB])
{ {
srslte_sequence_t seq; srslte_sequence_t seq;
bzero(&seq, sizeof(srslte_sequence_t)); bzero(&seq, sizeof(srslte_sequence_t));
@ -70,12 +144,12 @@ int srslte_generate_n_cs_cell(srslte_cell_t cell, uint32_t n_cs_cell[SRSLTE_NSLO
} }
/* Calculates alpha according to 5.5.2.2.2 of 36.211 */ /* Calculates alpha according to 5.5.2.2.2 (is_dmrs=true) or 5.4.1 (is_dmrs=false) of 36.211 */
float srslte_pucch_get_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB], float srslte_pucch_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
srslte_pucch_cfg_t *cfg, srslte_pucch_cfg_t *cfg,
srslte_cp_t cp, bool is_drms, srslte_cp_t cp, bool is_dmrs,
uint32_t ns, uint32_t l, uint32_t ns, uint32_t l,
uint32_t *n_oc_ptr) uint32_t *n_oc_ptr, uint32_t *n_prime_ns)
{ {
uint32_t c = SRSLTE_CP_ISNORM(cp)?3:2; uint32_t c = SRSLTE_CP_ISNORM(cp)?3:2;
uint32_t N_prime = (cfg->n_pucch < c*cfg->N_cs/cfg->delta_pucch_shift)?cfg->N_cs:12; uint32_t N_prime = (cfg->n_pucch < c*cfg->N_cs/cfg->delta_pucch_shift)?cfg->N_cs:12;
@ -84,11 +158,24 @@ float srslte_pucch_get_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP
if (cfg->n_pucch >= c*cfg->N_cs/cfg->delta_pucch_shift) { if (cfg->n_pucch >= c*cfg->N_cs/cfg->delta_pucch_shift) {
n_prime = (cfg->n_pucch-c*cfg->N_cs/cfg->delta_pucch_shift)%(cfg->N_cs/cfg->delta_pucch_shift); n_prime = (cfg->n_pucch-c*cfg->N_cs/cfg->delta_pucch_shift)%(cfg->N_cs/cfg->delta_pucch_shift);
} }
if (ns%2) {
if (cfg->n_pucch >= c*cfg->N_cs/cfg->delta_pucch_shift) {
n_prime = (c*(n_prime+1))%(c*SRSLTE_NRE/cfg->delta_pucch_shift+1)-1;
} else {
uint32_t d=SRSLTE_CP_ISNORM(cp)?2:0;
uint32_t h=(n_prime+d)%(c*N_prime/cfg->delta_pucch_shift);
n_prime = (h/c)+(h%c)*N_prime/cfg->delta_pucch_shift;
}
}
uint32_t n_oc_div = (!is_drms && SRSLTE_CP_ISEXT(cp))?2:1; if (n_prime_ns) {
*n_prime_ns = n_prime;
}
uint32_t n_oc_div = (!is_dmrs && SRSLTE_CP_ISEXT(cp))?2:1;
uint32_t n_oc = n_prime*cfg->delta_pucch_shift/N_prime; uint32_t n_oc = n_prime*cfg->delta_pucch_shift/N_prime;
if (!is_drms && SRSLTE_CP_ISEXT(cp)) { if (!is_dmrs && SRSLTE_CP_ISEXT(cp)) {
n_oc *= 2; n_oc *= 2;
} }
if (n_oc_ptr) { if (n_oc_ptr) {
@ -103,18 +190,34 @@ float srslte_pucch_get_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP
return 2 * M_PI * (n_cs) / 12; return 2 * M_PI * (n_cs) / 12;
} }
/* Map PUCCH symbols to physical resources according to 5.4.3 in 36.211 */
static int pucch_put(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, cf_t *output) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q && cfg && output) {
ret = SRSLTE_ERROR;
int pucch_cp(srslte_pucch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output, bool advance_input) // Determine m
{ uint32_t m = srslte_pucch_m(cfg, q->cell.cp);
return SRSLTE_ERROR;
}
int pucch_put(srslte_pucch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output) { uint32_t N_sf = get_N_sf(cfg->format);
return pucch_cp(q, harq, input, output, true); for (uint32_t ns=0;ns<2;ns++) {
} // Determine n_prb
uint32_t n_prb = m/2;
if ((m+ns)%2) {
n_prb = q->cell.nof_prb-1-m/2;
}
for (uint32_t i=0;i<N_sf;i++) {
uint32_t l = get_pucch_symbol(i, cfg->format, q->cell.cp);
memcpy(&output[SRSLTE_RE_IDX(q->cell.nof_prb, l, n_prb*SRSLTE_NRE)],
&q->z[i*SRSLTE_NRE+ns*N_sf*SRSLTE_NRE],
SRSLTE_NRE*sizeof(cf_t));
}
}
int pucch_get(srslte_pucch_t *q, srslte_harq_t *harq, cf_t *input, cf_t *output) { ret = SRSLTE_SUCCESS;
return pucch_cp(q, harq, input, output, false); }
return ret;
} }
@ -127,7 +230,12 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
q->cell = cell; q->cell = cell;
if (srslte_generate_n_cs_cell(q->cell, q->n_cs_cell)) { // Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
return SRSLTE_ERROR;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -140,13 +248,6 @@ void srslte_pucch_free(srslte_pucch_t *q) {
bzero(q, sizeof(srslte_pucch_t)); bzero(q, sizeof(srslte_pucch_t));
} }
/** Decodes the PUSCH from the received symbols
*/
int pucch_decode(srslte_pucch_t *q, srslte_harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint8_t *data)
{
return SRSLTE_ERROR_INVALID_INPUTS;
}
static cf_t uci_encode_format1() { static cf_t uci_encode_format1() {
return 1.0; return 1.0;
} }
@ -171,36 +272,84 @@ static cf_t uci_encode_format1b(uint8_t bits[2]) {
} }
} }
static void uci_mod_bits(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, uint8_t bits[SRSLTE_PUCCH_MAX_BITS]) /* Encode PUCCH bits according to Table 5.4.1-1 in Section 5.4.1 of 36.211 */
static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *d_0)
{ {
cf_t d_0 = 0; if (d_0) {
uint8_t tmp[2]; uint8_t tmp[2];
switch(cfg->format) { switch(cfg->format) {
case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_1:
d_0 = uci_encode_format1(); *d_0 = uci_encode_format1();
break; break;
case SRSLTE_PUCCH_FORMAT_1A: case SRSLTE_PUCCH_FORMAT_1A:
d_0 = uci_encode_format1a(bits[0]); *d_0 = uci_encode_format1a(bits[0]);
break; break;
case SRSLTE_PUCCH_FORMAT_1B: case SRSLTE_PUCCH_FORMAT_1B:
tmp[0] = bits[0]; tmp[0] = bits[0];
tmp[1] = bits[1]; tmp[1] = bits[1];
d_0 = uci_encode_format1b(tmp); *d_0 = uci_encode_format1b(tmp);
default: default:
fprintf(stderr, "PUCCH format 2 not supported\n"); fprintf(stderr, "PUCCH format 2 not supported\n");
return; return SRSLTE_ERROR;
} }
/*
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
q->y[n] = d_0+
} }
*/ return SRSLTE_SUCCESS;
} }
int srslte_pucch_encode(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *sf_symbols) // Declare this here, since we can not include refsignal_ul.h
void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u);
/* Encode, modulate and resource mapping of PUCCH bits according to Section 5.4.1 of 36.211 */
int srslte_pucch_encode(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, uint32_t sf_idx, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *sf_symbols)
{ {
uci_mod_bits(q, cfg, bits); int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
cfg != NULL &&
sf_symbols != NULL)
{
ret = SRSLTE_ERROR;
cf_t d_0 = 0;
if (uci_mod_bits(q, cfg, bits, &d_0)) {
fprintf(stderr, "Error encoding PUCCH bits\n");
return SRSLTE_ERROR;
}
uint32_t N_sf=get_N_sf(cfg->format);
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
// Get group hopping number u
uint32_t f_gh=0;
if (cfg->group_hopping_en) {
f_gh = q->f_gh[ns];
}
uint32_t u = (f_gh + (q->cell.id%30))%30;
srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u);
for (uint32_t m=0;m<N_sf;m++) {
uint32_t l = get_pucch_symbol(m, cfg->format, q->cell.cp);
uint32_t n_prime_ns;
uint32_t n_oc;
float alpha = srslte_pucch_alpha(q->n_cs_cell, cfg, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
uint32_t S_ns = 0;
if (n_prime_ns%2) {
S_ns = M_PI/2;
}
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = cfg->beta_pucch*d_0*w_n_oc[n_oc][m]*cexpf(I*(q->tmp_arg[n]+alpha*n+S_ns));
}
}
}
if (pucch_put(q, cfg, sf_symbols)) {
fprintf(stderr, "Error putting PUCCH symbols\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
}
ret = SRSLTE_SUCCESS;
}
return ret;
} }

@ -192,7 +192,7 @@ int main(int argc, char **argv) {
printf("Invalid received ACK: %d!=%d\n", ack[ngroup][nseq], ack_rx); printf("Invalid received ACK: %d!=%d\n", ack[ngroup][nseq], ack_rx);
exit(-1); exit(-1);
} }
if (distance) { if (distance < 5) {
printf("Error\n"); printf("Error\n");
exit(-1); exit(-1);
} }

@ -0,0 +1,223 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE 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.
*
* libLTE 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/mex/mexutils.h"
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define UECFG prhs[0]
#define PUSCHCFG prhs[1]
#define TRBLKIN prhs[2]
#define CQI prhs[3]
#define RI prhs[4]
#define ACK prhs[5]
#define NOF_INPUTS 6
void help()
{
mexErrMsgTxt
("sym=srslte_pusch_encode(ue, chs, trblkin, cqi, ri, ack)\n\n");
}
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nrhs != NOF_INPUTS) {
help();
return;
}
srslte_cell_t cell;
bzero(&cell, sizeof(srslte_cell_t));
cell.nof_ports = 1;
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
}
if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) {
mexErrMsgTxt("Field NULRB not found in UE config\n");
return;
}
srslte_pusch_t pusch;
if (srslte_pusch_init(&pusch, cell)) {
mexErrMsgTxt("Error initiating PUSCH\n");
return;
}
uint32_t rnti32=0;
if (mexutils_read_uint32_struct(UECFG, "RNTI", &rnti32)) {
mexErrMsgTxt("Field RNTI not found in pusch config\n");
return;
}
srslte_pusch_set_rnti(&pusch, (uint16_t) (rnti32 & 0xffff));
uint32_t sf_idx=0;
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
mexErrMsgTxt("Field NSubframe not found in UE config\n");
return;
}
srslte_ra_mcs_t mcs;
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) {
mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM;
} else {
mexErrMsgTxt("Unknown modulation\n");
return;
}
mxFree(mod_str);
float *prbset = NULL;
mxArray *p;
p = mxGetField(PUSCHCFG, 0, "PRBSet");
if (!p) {
mexErrMsgTxt("Error field PRBSet not found\n");
return;
}
srslte_ra_ul_alloc_t prb_alloc;
bzero(&prb_alloc, sizeof(srslte_ra_ul_alloc_t));
prb_alloc.L_prb = mexutils_read_f(p, &prbset);
prb_alloc.n_prb[0] = prbset[0];
prb_alloc.n_prb[1] = prbset[0];
free(prbset);
mexPrintf("L_prb: %d, n_prb: %d\n", prb_alloc.L_prb, prb_alloc.n_prb[2*sf_idx]);
uint8_t *trblkin = NULL;
mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
srslte_harq_t harq_process;
if (srslte_harq_init(&harq_process, cell)) {
mexErrMsgTxt("Error initiating HARQ process\n");
return;
}
if (srslte_harq_setup_ul(&harq_process, mcs, 0, sf_idx, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
if (!sf_symbols) {
mexErrMsgTxt("malloc");
return;
}
bzero(sf_symbols, sizeof(cf_t) * nof_re);
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &uci_data.uci_cqi);
uint8_t *tmp;
uci_data.uci_ri_len = mexutils_read_uint8(RI, &tmp);
if (uci_data.uci_ri_len > 0) {
uci_data.uci_ri = *tmp;
}
free(tmp);
uci_data.uci_ack_len = mexutils_read_uint8(ACK, &tmp);
if (uci_data.uci_ack_len > 0) {
uci_data.uci_ack = *tmp;
}
free(tmp);
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetCQI", &uci_data.I_offset_cqi)) {
uci_data.I_offset_cqi = 7;
}
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetRI", &uci_data.I_offset_ri)) {
uci_data.I_offset_ri = 2;
}
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetACK", &uci_data.I_offset_ack)) {
uci_data.I_offset_ack = 0;
}
mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", mcs.tbs,
uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ack, uci_data.uci_ri_len, uci_data.uci_ri);
mexPrintf("NofRE: %d, NofBits: %d, TBS: %d\n", harq_process.nof_re, harq_process.nof_bits, harq_process.mcs.tbs);
int r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols);
if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n");
return;
}
uint32_t rv=0;
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) {
mexErrMsgTxt("Field RV not found in pdsch config\n");
return;
}
if (rv > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv, sf_idx, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols);
if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n");
return;
}
}
cf_t *scfdma = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
bzero(scfdma, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_ofdm_t fft;
srslte_ofdm_tx_init(&fft, SRSLTE_CP_NORM, cell.nof_prb);
srslte_ofdm_set_normalize(&fft, true);
srslte_ofdm_set_freq_shift(&fft, 0.5);
srslte_ofdm_tx_sf(&fft, sf_symbols, scfdma);
// Matlab toolbox expects further normalization
srslte_vec_sc_prod_cfc(scfdma, 1.0/sqrtf(srslte_symbol_sz(cell.nof_prb)), scfdma, SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (nlhs >= 1) {
mexutils_write_cf(scfdma, &plhs[0], SRSLTE_SF_LEN_PRB(cell.nof_prb), 1);
}
if (nlhs >= 2) {
mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1);
}
if (nlhs >= 3) {
mexutils_write_cf(pusch.z, &plhs[2], harq_process.nof_re, 1);
}
srslte_pusch_free(&pusch);
free(trblkin);
free(uci_data.uci_cqi);
free(sf_symbols);
free(scfdma);
return;
}

@ -0,0 +1,274 @@
/**
*
* \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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/time.h>
#include "srslte/srslte.h"
srslte_cell_t cell = {
6, // nof_prb
1, // nof_ports
0, // cell_id
SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_SRSLTE_PHICH_R_1_6, // PHICH resources
SRSLTE_PHICH_NORM // PHICH length
};
uint32_t cfi = 2;
uint32_t tbs = 0;
uint32_t subframe = 1;
srslte_mod_t modulation = SRSLTE_MOD_QPSK;
uint32_t rv_idx = 0;
uint32_t L_prb = 2;
uint32_t n_prb = 0;
int freq_hop = -1;
int riv = -1;
void usage(char *prog) {
printf("Usage: %s [csrnfvmtLNF] -l TBS \n", prog);
printf("\t-m modulation (1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64) [Default BPSK]\n");
printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-s subframe [Default %d]\n", subframe);
printf("\t-L L_prb [Default %d]\n", L_prb);
printf("\t-N n_prb [Default %d]\n", n_prb);
printf("\t-F frequency hopping [Default %d]\n", freq_hop);
printf("\t-R RIV [Default %d]\n", riv);
printf("\t-r rv_idx [Default %d]\n", rv_idx);
printf("\t-f cfi [Default %d]\n", cfi);
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-v [set srslte_verbose to debug, default none]\n");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "lcnfvmtsrLNFR")) != -1) {
switch(opt) {
case 'm':
switch(atoi(argv[optind])) {
case 1:
modulation = SRSLTE_MOD_BPSK;
break;
case 2:
modulation = SRSLTE_MOD_QPSK;
break;
case 4:
modulation = SRSLTE_MOD_16QAM;
break;
case 6:
modulation = SRSLTE_MOD_64QAM;
break;
default:
fprintf(stderr, "Invalid modulation %d. Possible values: "
"(1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64)\n", atoi(argv[optind]));
break;
}
break;
case 's':
subframe = atoi(argv[optind]);
break;
case 'L':
L_prb = atoi(argv[optind]);
break;
case 'N':
n_prb = atoi(argv[optind]);
break;
case 'R':
riv = atoi(argv[optind]);
break;
case 'F':
freq_hop = atoi(argv[optind]);
break;
case 'r':
rv_idx = atoi(argv[optind]);
break;
case 'l':
tbs = atoi(argv[optind]);
break;
case 'n':
cell.nof_prb = atoi(argv[optind]);
break;
case 'c':
cell.id = atoi(argv[optind]);
break;
case 'v':
srslte_verbose++;
break;
default:
usage(argv[0]);
exit(-1);
}
}
}
int main(int argc, char **argv) {
srslte_pusch_t pusch;
uint8_t *data = NULL;
cf_t *sf_symbols = NULL;
int ret = -1;
struct timeval t[3];
srslte_ra_mcs_t mcs;
srslte_ra_ul_alloc_t prb_alloc;
srslte_harq_t harq_process;
parse_args(argc,argv);
mcs.tbs = tbs;
mcs.mod = modulation;
bzero(&prb_alloc, sizeof(srslte_ra_ul_alloc_t));
if (srslte_pusch_init(&pusch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
srslte_pusch_set_rnti(&pusch, 1234);
if (srslte_harq_init(&harq_process, cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
goto quit;
}
printf("Encoding rv_idx=%d\n",rv_idx);
uint8_t tmp[20];
for (uint32_t i=0;i<20;i++) {
tmp[i] = 1;
}
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_data.I_offset_cqi = 7;
uci_data.I_offset_ri = 2;
uci_data.I_offset_ack = 0;
uci_data.uci_cqi_len = 0;
uci_data.uci_ri_len = 0;
uci_data.uci_ack_len = 0;
uci_data.uci_cqi = tmp;
uci_data.uci_ri = 1;
uci_data.uci_ack = 1;
srslte_ra_pusch_t dci;
dci.freq_hop_fl = freq_hop;
if (riv < 0) {
dci.type2_alloc.L_crb = L_prb;
dci.type2_alloc.RB_start = n_prb;
} else {
srslte_ra_type2_from_riv((uint32_t) riv, &dci.type2_alloc.L_crb, &dci.type2_alloc.RB_start, cell.nof_prb, cell.nof_prb);
}
srslte_ra_ul_alloc(&prb_alloc, &dci, 0, cell.nof_prb);
if (srslte_harq_setup_ul(&harq_process, mcs, 0, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
srslte_pusch_hopping_cfg_t ul_hopping;
ul_hopping.n_sb = 1;
ul_hopping.hopping_offset = 0;
ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF;
ul_hopping.current_tx_nb = 0;
srslte_pusch_set_hopping_cfg(&pusch, &ul_hopping);
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
if (!sf_symbols) {
perror("malloc");
goto quit;
}
data = malloc(sizeof(uint8_t) * mcs.tbs);
if (!data) {
perror("malloc");
goto quit;
}
for (uint32_t i=0;i<mcs.tbs;i++) {
data[i] = 1;
}
if (srslte_pusch_uci_encode(&pusch, &harq_process, data, uci_data, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
if (rv_idx > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv_idx, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
if (srslte_pusch_uci_encode(&pusch, &harq_process, data, uci_data, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
}
cf_t *scfdma = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
bzero(scfdma, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_ofdm_t fft;
srslte_ofdm_tx_init(&fft, SRSLTE_CP_NORM, cell.nof_prb);
srslte_ofdm_set_freq_shift(&fft, 0.5);
srslte_ofdm_tx_sf(&fft, sf_symbols, scfdma);
gettimeofday(&t[1], NULL);
//int r = srslte_pusch_decode(&pusch, slot_symbols[0], ce, 0, data, subframe, &harq_process, rv);
int r = 0;
gettimeofday(&t[2], NULL);
get_time_interval(t);
if (r) {
printf("Error decoding\n");
ret = -1;
goto quit;
} else {
printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) mcs.tbs/t[0].tv_usec);
}
ret = 0;
quit:
srslte_pusch_free(&pusch);
srslte_harq_free(&harq_process);
if (sf_symbols) {
free(sf_symbols);
}
if (data) {
free(data);
}
if (ret) {
printf("Error\n");
} else {
printf("Ok\n");
}
exit(ret);
}

@ -33,17 +33,14 @@
*/ */
#define UECFG prhs[0] #define UECFG prhs[0]
#define PUSCHCFG prhs[1] #define PUCCHCFG prhs[1]
#define TRBLKIN prhs[2] #define ACK prhs[2]
#define CQI prhs[3] #define NOF_INPUTS 3
#define RI prhs[4]
#define ACK prhs[5]
#define NOF_INPUTS 6
void help() void help()
{ {
mexErrMsgTxt mexErrMsgTxt
("sym=srslte_pusch_encode(ue, chs, trblkin, cqi, ri, ack)\n\n"); ("[subframe, subframe_with_dmrs]=srslte_pucch_encode(ue, chs, ack)\n\n");
} }
/* the gateway function */ /* the gateway function */
@ -58,6 +55,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_cell_t cell; srslte_cell_t cell;
bzero(&cell, sizeof(srslte_cell_t)); bzero(&cell, sizeof(srslte_cell_t));
cell.nof_ports = 1; cell.nof_ports = 1;
cell.cp = SRSLTE_CP_NORM;
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) { if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
mexErrMsgTxt("Field NCellID not found in UE config\n"); mexErrMsgTxt("Field NCellID not found in UE config\n");
return; return;
@ -66,157 +64,101 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Field NULRB not found in UE config\n"); mexErrMsgTxt("Field NULRB not found in UE config\n");
return; return;
} }
srslte_pusch_t pusch; srslte_pucch_t pucch;
if (srslte_pusch_init(&pusch, cell)) { if (srslte_pucch_init(&pucch, cell)) {
mexErrMsgTxt("Error initiating PUSCH\n"); mexErrMsgTxt("Error initiating PUSCH\n");
return; return;
} }
uint32_t rnti32=0;
if (mexutils_read_uint32_struct(UECFG, "RNTI", &rnti32)) {
mexErrMsgTxt("Field RNTI not found in pusch config\n");
return;
}
srslte_pusch_set_rnti(&pusch, (uint16_t) (rnti32 & 0xffff));
uint32_t sf_idx=0; uint32_t sf_idx = 0;
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) { if (mexutils_read_uint32_struct(UECFG, "NSubframe", &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; srslte_pucch_cfg_t pucch_cfg;
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); if (mexutils_read_uint32_struct(PUCCHCFG, "ResourceIdx", &pucch_cfg.n_pucch)) {
if (!strcmp(mod_str, "QPSK")) { mexErrMsgTxt("Field ResourceIdx not found in PUCCHCFG\n");
mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) {
mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) {
mcs.mod = SRSLTE_MOD_64QAM;
} else {
mexErrMsgTxt("Unknown modulation\n");
return; return;
} }
if (mexutils_read_uint32_struct(PUCCHCFG, "DeltaShift", &pucch_cfg.delta_pucch_shift)) {
mxFree(mod_str); mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n");
float *prbset = NULL;
mxArray *p;
p = mxGetField(PUSCHCFG, 0, "PRBSet");
if (!p) {
mexErrMsgTxt("Error field PRBSet not found\n");
return; return;
} }
if (mexutils_read_uint32_struct(PUCCHCFG, "CyclicShifts", &pucch_cfg.N_cs)) {
srslte_ra_ul_alloc_t prb_alloc; mexErrMsgTxt("Field CyclicShifts not found in PUCCHCFG\n");
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);
mexPrintf("L_prb: %d, n_prb: %d\n", prb_alloc.L_prb, prb_alloc.n_prb[2*sf_idx]);
uint8_t *trblkin = NULL;
mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
srslte_harq_t harq_process;
if (srslte_harq_init(&harq_process, cell)) {
mexErrMsgTxt("Error initiating HARQ process\n");
return; return;
} }
if (srslte_harq_setup_ul(&harq_process, mcs, 0, sf_idx, &prb_alloc)) { pucch_cfg.group_hopping_en = false;
mexErrMsgTxt("Error configuring HARQ process\n"); char *hop = mexutils_get_char_struct(PUCCHCFG, "Hopping");
return; if (hop) {
if (!strcmp(hop, "Group")) {
pucch_cfg.group_hopping_en = true;
} }
mxFree(hop);
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
if (!sf_symbols) {
mexErrMsgTxt("malloc");
return;
} }
bzero(sf_symbols, sizeof(cf_t) * nof_re);
uint8_t bits[SRSLTE_PUCCH_MAX_BITS];
srslte_uci_data_t uci_data; float *bits_ptr;
bzero(&uci_data, sizeof(srslte_uci_data_t)); int n = mexutils_read_f(ACK, &bits_ptr);
uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &uci_data.uci_cqi); for (int i=0;i<n;i++) {
uint8_t *tmp; bits[i] = bits_ptr>0?1:0;
uci_data.uci_ri_len = mexutils_read_uint8(RI, &tmp);
if (uci_data.uci_ri_len > 0) {
uci_data.uci_ri = *tmp;
}
free(tmp);
uci_data.uci_ack_len = mexutils_read_uint8(ACK, &tmp);
if (uci_data.uci_ack_len > 0) {
uci_data.uci_ack = *tmp;
} }
free(tmp); free(bits_ptr);
switch(n) {
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetCQI", &uci_data.I_offset_cqi)) { case 0:
uci_data.I_offset_cqi = 7; pucch_cfg.format = SRSLTE_PUCCH_FORMAT_1;
break;
case 1:
pucch_cfg.format = SRSLTE_PUCCH_FORMAT_1A;
break;
case 2:
pucch_cfg.format = SRSLTE_PUCCH_FORMAT_1B;
break;
default:
mexErrMsgTxt("Invalid number of bits in parameter ack\n");
return;
} }
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetRI", &uci_data.I_offset_ri)) {
uci_data.I_offset_ri = 2; cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!sf_symbols) {
return;
} }
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetACK", &uci_data.I_offset_ack)) { bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
uci_data.I_offset_ack = 0; if (srslte_pucch_encode(&pucch, &pucch_cfg, sf_idx, bits, sf_symbols)) {
mexErrMsgTxt("Error encoding PUCCH\n");
return;
} }
mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", 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);
if (nlhs >= 1) {
mexutils_write_cf(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
}
mexPrintf("NofRE: %d, NofBits: %d, TBS: %d\n", harq_process.nof_re, harq_process.nof_bits, harq_process.mcs.tbs); if (nlhs >= 2) {
int r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols); srslte_refsignal_ul_t pucch_dmrs;
if (r < 0) { if (srslte_refsignal_ul_init(&pucch_dmrs, cell)) {
mexErrMsgTxt("Error encoding PUSCH\n"); mexErrMsgTxt("Error initiating PUCCH DMRS\n");
return; return;
} }
uint32_t rv=0; cf_t *dmrs_pucch = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_NRE*3);
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) { if (!dmrs_pucch) {
mexErrMsgTxt("Field RV not found in pdsch config\n");
return; return;
} }
if (rv > 0) { if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, &pucch_cfg, sf_idx, dmrs_pucch)) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv, sf_idx, &prb_alloc)) { mexErrMsgTxt("Error generating PUCCH DMRS\n");
mexErrMsgTxt("Error configuring HARQ process\n");
return; return;
} }
r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols); if (srslte_refsignal_dmrs_pucch_put(&pucch_dmrs, &pucch_cfg, dmrs_pucch, sf_symbols)) {
if (r < 0) { mexErrMsgTxt("Error generating PUCCH DMRS\n");
mexErrMsgTxt("Error encoding PUSCH\n");
return; return;
} }
mexutils_write_cf(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
srslte_refsignal_ul_free(&pucch_dmrs);
free(dmrs_pucch);
} }
cf_t *scfdma = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); srslte_pucch_free(&pucch);
bzero(scfdma, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_ofdm_t fft;
srslte_ofdm_tx_init(&fft, SRSLTE_CP_NORM, cell.nof_prb);
srslte_ofdm_set_normalize(&fft, true);
srslte_ofdm_set_freq_shift(&fft, 0.5);
srslte_ofdm_tx_sf(&fft, sf_symbols, scfdma);
// Matlab toolbox expects further normalization
srslte_vec_sc_prod_cfc(scfdma, 1.0/sqrtf(srslte_symbol_sz(cell.nof_prb)), scfdma, SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (nlhs >= 1) {
mexutils_write_cf(scfdma, &plhs[0], SRSLTE_SF_LEN_PRB(cell.nof_prb), 1);
}
if (nlhs >= 2) {
mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1);
}
if (nlhs >= 3) {
mexutils_write_cf(pusch.z, &plhs[2], harq_process.nof_re, 1);
}
srslte_pusch_free(&pusch);
free(trblkin);
free(uci_data.uci_cqi);
free(sf_symbols); free(sf_symbols);
free(scfdma);
return; return;
} }

@ -192,8 +192,8 @@ srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, cf_t *input, uint32_t peak_p
float R_norm, R_ext, C_norm, C_ext; float R_norm, R_ext, C_norm, C_ext;
float M_norm=0, M_ext=0; float M_norm=0, M_ext=0;
uint32_t cp_norm_len = SRSLTE_CP_NORM(7, q->fft_size); uint32_t cp_norm_len = SRSLTE_CP_LEN_NORM(7, q->fft_size);
uint32_t cp_ext_len = SRSLTE_CP_EXT(q->fft_size); uint32_t cp_ext_len = SRSLTE_CP_LEN_EXT(q->fft_size);
cf_t *input_cp_norm = &input[peak_pos-2*(q->fft_size+cp_norm_len)]; cf_t *input_cp_norm = &input[peak_pos-2*(q->fft_size+cp_norm_len)];
cf_t *input_cp_ext = &input[peak_pos-2*(q->fft_size+cp_ext_len)]; cf_t *input_cp_ext = &input[peak_pos-2*(q->fft_size+cp_ext_len)];
@ -240,7 +240,7 @@ int sync_sss(srslte_sync_t *q, cf_t *input, uint32_t peak_pos, srslte_cp_t cp) {
srslte_sss_synch_set_N_id_2(&q->sss, q->N_id_2); srslte_sss_synch_set_N_id_2(&q->sss, q->N_id_2);
/* Make sure we have enough room to find SSS sequence */ /* Make sure we have enough room to find SSS sequence */
sss_idx = (int) peak_pos-2*q->fft_size-SRSLTE_CP(q->fft_size, (SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_NORM_LEN:SRSLTE_CP_EXT_LEN)); sss_idx = (int) peak_pos-2*q->fft_size-SRSLTE_CP_LEN(q->fft_size, (SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_NORM_LEN:SRSLTE_CP_EXT_LEN));
if (sss_idx < 0) { if (sss_idx < 0) {
INFO("Not enough room to decode CP SSS (sss_idx=%d, peak_pos=%d)\n", sss_idx, peak_pos); INFO("Not enough room to decode CP SSS (sss_idx=%d, peak_pos=%d)\n", sss_idx, peak_pos);
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -325,7 +325,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
} }
if (q->detect_cp) { if (q->detect_cp) {
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_EXT(q->fft_size))) { if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
q->cp = srslte_sync_detect_cp(q, input, peak_pos + find_offset); q->cp = srslte_sync_detect_cp(q, input, peak_pos + find_offset);
} else { } else {
INFO("Not enough room to detect CP length. Peak position: %d\n", peak_pos); INFO("Not enough room to detect CP length. Peak position: %d\n", peak_pos);

@ -231,7 +231,7 @@ int main(int argc, char **argv) {
} }
// Find SSS // Find SSS
int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP(fft_size, SRSLTE_CP_EXT_LEN)); int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP_LEN(fft_size, SRSLTE_CP_EXT_LEN));
if (sss_idx >= 0 && sss_idx < flen-fft_size) { if (sss_idx >= 0 && sss_idx < flen-fft_size) {
srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value); srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value);
if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
@ -251,7 +251,7 @@ int main(int argc, char **argv) {
} }
// Estimate CP // Estimate CP
if (peak_idx > 2*(fft_size + SRSLTE_CP_EXT(fft_size))) { if (peak_idx > 2*(fft_size + SRSLTE_CP_LEN_EXT(fft_size))) {
srslte_cp_t cp = srslte_sync_detect_cp(&ssync, buffer, peak_idx); srslte_cp_t cp = srslte_sync_detect_cp(&ssync, buffer, peak_idx);
if (SRSLTE_CP_ISNORM(cp)) { if (SRSLTE_CP_ISNORM(cp)) {
cp_is_norm++; cp_is_norm++;

@ -241,7 +241,7 @@ int main(int argc, char **argv) {
} }
// Find SSS // Find SSS
int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP(fft_size, SRSLTE_CP_EXT_LEN)); int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP_LEN(fft_size, SRSLTE_CP_EXT_LEN));
if (sss_idx >= 0 && sss_idx < flen-fft_size) { if (sss_idx >= 0 && sss_idx < flen-fft_size) {
srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value); srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value);
if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
@ -261,7 +261,7 @@ int main(int argc, char **argv) {
} }
// Estimate CP // Estimate CP
if (peak_idx > 2*(fft_size + SRSLTE_CP_EXT(fft_size))) { if (peak_idx > 2*(fft_size + SRSLTE_CP_LEN_EXT(fft_size))) {
srslte_cp_t cp = srslte_sync_detect_cp(&ssync, buffer, peak_idx); srslte_cp_t cp = srslte_sync_detect_cp(&ssync, buffer, peak_idx);
if (SRSLTE_CP_ISNORM(cp)) { if (SRSLTE_CP_ISNORM(cp)) {
cp_is_norm++; cp_is_norm++;

@ -76,7 +76,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
goto clean_exit; goto clean_exit;
} }
} }
if (srslte_refsignal_ul_init(&q->drms, 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");
goto clean_exit; goto clean_exit;
} }
@ -112,7 +112,7 @@ void srslte_ue_ul_free(srslte_ue_ul_t *q) {
srslte_harq_free(&q->harq_process[i]); srslte_harq_free(&q->harq_process[i]);
} }
srslte_cfo_free(&q->cfo); srslte_cfo_free(&q->cfo);
srslte_refsignal_ul_free(&q->drms); srslte_refsignal_ul_free(&q->dmrs);
if (q->sf_symbols) { if (q->sf_symbols) {
free(q->sf_symbols); free(q->sf_symbols);
@ -151,9 +151,9 @@ void srslte_ue_ul_reset(srslte_ue_ul_t *q) {
srslte_harq_reset(&q->harq_process[0]); srslte_harq_reset(&q->harq_process[0]);
} }
void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q, srslte_refsignal_drms_pusch_cfg_t *drms_cfg, srslte_pusch_hopping_cfg_t *pusch_hopping_cfg) void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg, srslte_pusch_hopping_cfg_t *pusch_hopping_cfg)
{ {
memcpy(&q->drms_cfg, drms_cfg, sizeof(srslte_refsignal_drms_pusch_cfg_t)); memcpy(&q->dmrs_cfg, dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg); srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg);
} }
@ -206,13 +206,13 @@ int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_
} }
// FIXME: Pregenerate for all possible number of prb // FIXME: Pregenerate for all possible number of prb
if (srslte_refsignal_dmrs_gen(&q->drms, &q->drms_cfg, if (srslte_refsignal_dmrs_pusch_gen(&q->dmrs, &q->dmrs_cfg,
q->harq_process[0].ul_alloc.L_prb, sf_idx, q->refsignal)) q->harq_process[0].ul_alloc.L_prb, 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_drms_pusch_put(&q->drms, &q->drms_cfg, q->refsignal, srslte_refsignal_dmrs_pusch_put(&q->dmrs, &q->dmrs_cfg, q->refsignal,
q->harq_process[0].ul_alloc.L_prb, q->harq_process[0].ul_alloc.L_prb,
q->harq_process[0].ul_alloc.n_prb_tilde, q->harq_process[0].ul_alloc.n_prb_tilde,
q->sf_symbols); q->sf_symbols);

@ -79,14 +79,14 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant,
return false; return false;
} }
srslte_refsignal_drms_pusch_cfg_t drms_cfg; srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
bzero(&drms_cfg, sizeof(srslte_refsignal_drms_pusch_cfg_t)); bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
drms_cfg.beta_pusch = (float) params_db->get_param(params::PUSCH_BETA)/10; dmrs_cfg.beta_pusch = (float) params_db->get_param(params::PUSCH_BETA)/10;
drms_cfg.group_hopping_en = params_db->get_param(params::PUSCH_RS_GROUP_HOPPING_EN); dmrs_cfg.group_hopping_en = params_db->get_param(params::PUSCH_RS_GROUP_HOPPING_EN);
drms_cfg.sequence_hopping_en = params_db->get_param(params::PUSCH_RS_SEQUENCE_HOPPING_EN); dmrs_cfg.sequence_hopping_en = params_db->get_param(params::PUSCH_RS_SEQUENCE_HOPPING_EN);
drms_cfg.cyclic_shift = params_db->get_param(params::PUSCH_RS_CYCLIC_SHIFT); dmrs_cfg.cyclic_shift = params_db->get_param(params::PUSCH_RS_CYCLIC_SHIFT);
drms_cfg.delta_ss = params_db->get_param(params::PUSCH_RS_GROUP_ASSIGNMENT); dmrs_cfg.delta_ss = params_db->get_param(params::PUSCH_RS_GROUP_ASSIGNMENT);
srslte_pusch_hopping_cfg_t pusch_hopping; srslte_pusch_hopping_cfg_t pusch_hopping;
pusch_hopping.n_sb = params_db->get_param(params::PUSCH_HOPPING_N_SB); pusch_hopping.n_sb = params_db->get_param(params::PUSCH_HOPPING_N_SB);
@ -96,7 +96,7 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant,
pusch_hopping.hopping_offset = params_db->get_param(params::PUSCH_HOPPING_OFFSET); pusch_hopping.hopping_offset = params_db->get_param(params::PUSCH_HOPPING_OFFSET);
pusch_hopping.current_tx_nb = pusch_grant.get_current_tx_nb(); pusch_hopping.current_tx_nb = pusch_grant.get_current_tx_nb();
srslte_ue_ul_set_pusch_cfg(&ue_ul, &drms_cfg, &pusch_hopping); srslte_ue_ul_set_pusch_cfg(&ue_ul, &dmrs_cfg, &pusch_hopping);
int n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(), int n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(),
payload, uci_data, payload, uci_data,

@ -242,7 +242,7 @@ int main(int argc, char **argv) {
} }
// Find SSS // Find SSS
int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP(fft_size, SRSLTE_CP_EXT_LEN)); int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP_LEN(fft_size, SRSLTE_CP_EXT_LEN));
if (sss_idx >= 0 && sss_idx < flen-fft_size) { if (sss_idx >= 0 && sss_idx < flen-fft_size) {
srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value); srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value);
if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
@ -262,7 +262,7 @@ int main(int argc, char **argv) {
} }
// Estimate CP // Estimate CP
if (peak_idx > 2*(fft_size + SRSLTE_CP_EXT(fft_size))) { if (peak_idx > 2*(fft_size + SRSLTE_CP_LEN_EXT(fft_size))) {
srslte_cp_t cp = srslte_sync_detect_cp(&ssync, buffer, peak_idx); srslte_cp_t cp = srslte_sync_detect_cp(&ssync, buffer, peak_idx);
if (SRSLTE_CP_ISNORM(cp)) { if (SRSLTE_CP_ISNORM(cp)) {
cp_is_norm++; cp_is_norm++;

Loading…
Cancel
Save