PUCCH Formats 1/1a/1b verified with Matlab

master
ismagom 10 years ago
parent 705f4b1347
commit 571e45f48d

@ -1,75 +1,59 @@
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);
ueConfig=struct('NCellID',2,'NULRB',6,'NSubframe',7,'CyclicPrefixUL','Normal','NTxAnts',1,'Hopping','Off');
pucchConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0,'ResourceSize',0);
addpath('../../debug/lte/phy/lib/phch/test')
addpath('../../debug/srslte/lib/phch/test')
% TBs=0:13:211;
% cqilen=[0, 8, 17];
% mods={'QPSK','16QAM','64QAM'};
% rvs=0;
% betas=0:3:11;
k=1;
for f=0:2
for n=0:130
for d=1:3
for ncs=0:d:7
pucchConfig.ResourceIdx= n;
pucchConfig.DeltaShift = d;
pucchConfig.CyclicShifts = ncs;
ack=randi(2,f,1)-1;
fprintf('Testint Format: %d, n_pucch=%d, DeltaShift=%d, CyclicShift=%d\n',f,n,d,ncs);
[sym_mat, info]=ltePUCCH1(ueConfig,pucchConfig,ack);
idx=ltePUCCH1Indices(ueConfig,pucchConfig);
[dmrs_mat, info_dmrs]=ltePUCCH1DRS(ueConfig,pucchConfig);
idx_dmrs=ltePUCCH1DRSIndices(ueConfig,pucchConfig);
subframe_mat = lteULResourceGrid(ueConfig);
subframe_mat(idx)=sym_mat;
subframe_mat(idx_dmrs)=dmrs_mat;
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);
[sym, dmrs]=srslte_pucch_encode(ueConfig,pucchConfig,ack);
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
error_sym=mean(abs(sym-sym_mat));
error_dmrs=mean(abs(dmrs-dmrs_mat));
%error_sf=mean(abs(subframe_mat(:)-subframe_lib));
k=k+1;
if (error_sym > 1e-6)
disp(info)
plot(angle(sym)-angle(sym_mat))
error('Error in symbols');
end
if (error_dmrs > 1e-6)
disp(info_dmrs)
plot(angle(dmrs)-angle(dmrs_mat))
error('Error in DMRS');
end
% if (error_sf > 1e-6)
% disp(info)
% p=1:length(subframe_lib);
% plot(p,real(subframe_lib(p)),p,real(subframe_mat(p)))
% error('Error in subframe');
% 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))
if (k == 2)
disp(info)
disp(error_sym)
disp(error_sf)
n=1:length(sym);
plot(n,real(sym(n)),n,real(sym_mat(n)))
end

@ -62,6 +62,9 @@ typedef struct SRSLTE_API {
/** Uplink DeModulation Reference Signal (DMRS) */
typedef struct SRSLTE_API {
srslte_cell_t cell;
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
srslte_pucch_cfg_t pucch_cfg;
uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB];
float *tmp_arg;
uint32_t n_prs_pusch[SRSLTE_NOF_DELTA_SS][SRSLTE_NSLOTS_X_FRAME]; // We precompute n_prs needed for cyclic shift alpha at srslte_refsignal_dl_init()
@ -76,6 +79,12 @@ 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_set_pusch_cfg(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *cfg);
SRSLTE_API bool srslte_refsignal_ul_set_pucch_cfg(srslte_refsignal_ul_t *q,
srslte_pucch_cfg_t *cfg);
SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float *arg,
uint32_t u);
@ -84,30 +93,29 @@ SRSLTE_API bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q
uint32_t nof_prb);
SRSLTE_API 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);
SRSLTE_API void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *cfg,
cf_t *r_pusch,
uint32_t nof_prb,
uint32_t n_prb[2],
cf_t *sf_symbols);
SRSLTE_API int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q,
srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format,
uint32_t n_pucch,
uint32_t sf_idx,
cf_t *r_pucch);
SRSLTE_API int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q,
srslte_pucch_cfg_t* cfg,
srslte_pucch_format_t format,
uint32_t n_pucch,
cf_t *r_pucch,
cf_t *output);
SRSLTE_API void srslte_refsignal_srs_gen(srslte_refsignal_ul_t *q,
srslte_refsignal_srs_cfg_t *cfg,
uint32_t sf_idx,
cf_t *r_srs);

@ -41,7 +41,7 @@
#define SRSLTE_PUCCH_N_SEQ 12 // Only Format 1, 1a and 1b supported
#define SRSLTE_PUCCH_MAX_BITS 2
#define SRSLTE_PUCCH_N_SF_MAX 4
#define SRSLTE_PUCCH_N_SF_MAX 5
typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_1 = 0,
@ -53,10 +53,8 @@ typedef enum SRSLTE_API {
} srslte_pucch_format_t;
typedef struct SRSLTE_API {
srslte_pucch_format_t format;
float beta_pucch;
uint32_t delta_pucch_shift;
uint32_t n_pucch;
uint32_t n_rb_2;
uint32_t N_cs;
bool group_hopping_en;
@ -70,7 +68,7 @@ typedef struct SRSLTE_API {
uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB];
uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME];
float tmp_arg[SRSLTE_PUCCH_N_SEQ];
float z[SRSLTE_PUCCH_N_SF_MAX*SRSLTE_PUCCH_N_SEQ];
cf_t z[2*SRSLTE_PUCCH_N_SF_MAX*SRSLTE_PUCCH_N_SEQ];
}srslte_pucch_t;
@ -79,20 +77,18 @@ SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q,
SRSLTE_API void srslte_pucch_free(srslte_pucch_t *q);
SRSLTE_API void srslte_pucch_set_cfg(srslte_pucch_t *q,
srslte_pucch_cfg_t *cfg);
SRSLTE_API int srslte_pucch_set_rnti(srslte_pucch_t *q,
uint16_t rnti);
SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q, srslte_pucch_cfg_t* cfg);
SRSLTE_API int srslte_pucch_encode(srslte_pucch_t *q,
srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format,
uint32_t n_pucch,
uint32_t sf_idx,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS],
cf_t *sf_symbols);
SRSLTE_API float srslte_pucch_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
srslte_pucch_cfg_t *cfg,
uint32_t n_pucch,
srslte_cp_t cp,
bool is_dmrs,
uint32_t ns,
@ -101,12 +97,20 @@ SRSLTE_API float srslte_pucch_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SR
uint32_t *n_prime_ns);
SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format,
uint32_t n_pucch,
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]);
SRSLTE_API bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg);
SRSLTE_API bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg,
uint32_t nof_prb);
SRSLTE_API bool srslte_n_pucch_isvalid(srslte_pucch_t *q,
uint32_t n_pucch);
SRSLTE_API void srslte_pucch_cfg_default(srslte_pucch_cfg_t *cfg);
#endif

@ -63,8 +63,6 @@ typedef struct SRSLTE_API {
float current_cfo;
srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
srslte_refsignal_ul_t dmrs;
srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES];
srslte_pusch_t pusch;

@ -132,6 +132,8 @@ int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell)
goto free_and_exit;
}
srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute n_prs
if (generate_n_prs(q)) {
goto free_and_exit;
@ -168,6 +170,21 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
}
void srslte_refsignal_ul_set_pusch_cfg(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg)
{
memcpy(&q->pusch_cfg, cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
}
bool srslte_refsignal_ul_set_pucch_cfg(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t *cfg)
{
if (srslte_pucch_cfg_isvalid(cfg, q->cell.nof_prb)) {
memcpy(&q->pucch_cfg, cfg, sizeof(srslte_pucch_cfg_t));
return true;
} else {
return false;
}
}
uint32_t largest_prime_lower_than(uint32_t x) {
/* get largest prime n_zc<len */
for (uint32_t i = NOF_PRIME_NUMBERS - 1; i > 0; i--) {
@ -244,11 +261,7 @@ bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q, srslte_re
}
}
void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg,
cf_t *r_pusch,
uint32_t nof_prb,
uint32_t n_prb[2],
cf_t *sf_symbols)
void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, cf_t *r_pusch, uint32_t nof_prb, uint32_t n_prb[2], cf_t *sf_symbols)
{
for (uint32_t ns_idx=0;ns_idx<2;ns_idx++) {
DEBUG("Putting DRMS to n_prb: %d, L: %d, ns_idx: %d\n", n_prb[ns_idx], nof_prb, ns_idx);
@ -259,43 +272,43 @@ void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, srslte_refsignal_
}
/* Generate DRMS for PUSCH signal according to 5.5.2.1 of 36.211 */
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 srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t sf_idx, cf_t *r_pusch)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (srslte_refsignal_dmrs_pusch_cfg_isvalid(q, cfg, nof_prb)) {
if (srslte_refsignal_dmrs_pusch_cfg_isvalid(q, &q->pusch_cfg, nof_prb)) {
ret = SRSLTE_ERROR;
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) {
if (q->pusch_cfg.group_hopping_en) {
f_gh = q->f_gh[ns];
}
uint32_t u = (f_gh + (q->cell.id%30)+cfg->delta_ss)%30;
uint32_t u = (f_gh + (q->cell.id%30)+q->pusch_cfg.delta_ss)%30;
// Get sequence hopping number v
uint32_t v = 0;
if (nof_prb >= 6 && cfg->sequence_hopping_en) {
v = q->v_pusch[ns][cfg->delta_ss];
if (nof_prb >= 6 && q->pusch_cfg.sequence_hopping_en) {
v = q->v_pusch[ns][q->pusch_cfg.delta_ss];
}
// Compute signal argument
compute_pusch_r_uv_arg(q, cfg, nof_prb, u, v);
compute_pusch_r_uv_arg(q, &q->pusch_cfg, nof_prb, u, v);
// Add cyclic prefix alpha
float alpha = pusch_alpha(q, cfg, ns);
float alpha = pusch_alpha(q, &q->pusch_cfg, ns);
if (srslte_verbose == SRSLTE_VERBOSE_DEBUG) {
uint32_t N_sz = largest_prime_lower_than(nof_prb*SRSLTE_NRE);
DEBUG("Generating PUSCH DRMS sequence with parameters:\n",0);
DEBUG("\tbeta: %.1f, nof_prb: %d, u: %d, v: %d, alpha: %f, N_sc: %d, root q: %d, nprs: %d\n",
cfg->beta_pusch, nof_prb, u, v, alpha, N_sz, get_q(u,v,N_sz),q->n_prs_pusch[cfg->delta_ss][ns]);
q->pusch_cfg.beta_pusch, nof_prb, u, v, alpha, N_sz, get_q(u,v,N_sz),q->n_prs_pusch[q->pusch_cfg.delta_ss][ns]);
}
// Do complex exponential and adjust amplitude
for (int i=0;i<SRSLTE_NRE*nof_prb;i++) {
r_pusch[(ns%2)*SRSLTE_NRE*nof_prb+i] = cfg->beta_pusch * cexpf(I*(q->tmp_arg[i] + alpha*i));
r_pusch[(ns%2)*SRSLTE_NRE*nof_prb+i] = q->pusch_cfg.beta_pusch * cexpf(I*(q->tmp_arg[i] + alpha*i));
}
}
ret = 0;
@ -362,18 +375,18 @@ static uint32_t get_pucch_dmrs_symbol(uint32_t m, srslte_pucch_format_t format,
}
/* 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 srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx, cf_t *r_pucch)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (srslte_pucch_cfg_isvalid(cfg)) {
if (q && r_pucch) {
ret = SRSLTE_ERROR;
uint32_t N_rs=get_N_rs(cfg->format, q->cell.cp);
uint32_t N_rs=get_N_rs(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) {
if (q->pucch_cfg.group_hopping_en) {
f_gh = q->f_gh[ns];
}
uint32_t u = (f_gh + (q->cell.id%30))%30;
@ -383,13 +396,13 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t
for (uint32_t m=0;m<N_rs;m++) {
uint32_t n_oc=0;
uint32_t l = get_pucch_dmrs_symbol(m, cfg->format, q->cell.cp);
uint32_t l = get_pucch_dmrs_symbol(m, format, q->cell.cp);
// Add cyclic prefix alpha
float alpha = srslte_pucch_alpha(q->n_cs_cell, cfg, q->cell.cp, true, ns, l, &n_oc, NULL);
float alpha = srslte_pucch_alpha(q->n_cs_cell, &q->pucch_cfg, n_pucch, 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
float *w=NULL;
switch (cfg->format) {
switch (format) {
case SRSLTE_PUCCH_FORMAT_1:
case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B:
@ -414,7 +427,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t
if (w) {
for (uint32_t n=0;n<SRSLTE_NRE;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));
r_pucch[(ns%2)*SRSLTE_NRE*N_rs+m*SRSLTE_NRE+n] = q->pucch_cfg.beta_pucch*cexpf(I*(w[m]+q->tmp_arg[n]+alpha*n));
}
} else {
return SRSLTE_ERROR;
@ -427,16 +440,16 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t
}
/* 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 srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *r_pucch, cf_t *output)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q && cfg && output) {
if (q && output) {
ret = SRSLTE_ERROR;
// Determine m
uint32_t m = srslte_pucch_m(cfg, q->cell.cp);
uint32_t m = srslte_pucch_m(&q->pucch_cfg, format, n_pucch, q->cell.cp);
uint32_t N_rs = get_N_rs(cfg->format, q->cell.cp);
uint32_t N_rs = get_N_rs(format, q->cell.cp);
for (uint32_t ns=0;ns<2;ns++) {
// Determine n_prb
uint32_t n_prb = m/2;
@ -445,7 +458,7 @@ int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t
}
for (uint32_t i=0;i<N_rs;i++) {
uint32_t l = get_pucch_dmrs_symbol(m, cfg->format, q->cell.cp);
uint32_t l = get_pucch_dmrs_symbol(m, 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));
@ -457,7 +470,7 @@ int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t
return ret;
}
void srslte_refsignal_srs_gen(srslte_refsignal_ul_t *q, srslte_refsignal_srs_cfg_t *cfg, uint32_t ns, cf_t *r_srs)
void srslte_refsignal_srs_gen(srslte_refsignal_ul_t *q, uint32_t ns, cf_t *r_srs)
{
}

@ -134,12 +134,15 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t));
srslte_refsignal_ul_set_pusch_cfg(&refs, &pusch_cfg);
//mexPrintf("Generating DRMS for ns=%d, nof_prb=%d\n", 2*sf_idx+i,pusch_cfg.nof_prb);
srslte_refsignal_dmrs_pusch_gen(&refs, &pusch_cfg, nof_prb, sf_idx, signal);
srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, signal);
uint32_t n_prb[2];
n_prb[0] = prbset[0];
n_prb[1] = prbset[0];
srslte_refsignal_dmrs_pusch_put(&refs, &pusch_cfg, signal, nof_prb, n_prb, sf_symbols);
srslte_refsignal_dmrs_pusch_put(&refs, signal, nof_prb, n_prb, sf_symbols);
if (nlhs >= 1) {
mexutils_write_cf(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
}

@ -123,7 +123,8 @@ int main(int argc, char **argv) {
printf("cyclic_shift_for_dmrs: %d, ",pusch_cfg.cyclic_shift_for_dmrs);
printf("delta_ss: %d, ",pusch_cfg.delta_ss);
printf("SF_idx: %d\n", sf_idx);
srslte_refsignal_dmrs_pusch_gen(&refs, &pusch_cfg, nof_prb, sf_idx, signal);
srslte_refsignal_ul_set_pusch_cfg(&refs, &pusch_cfg);
srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, signal);
exit(0);
}
}

@ -53,8 +53,21 @@ 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) {
return true;
/* Verify PUCCH configuration as given in Section 5.4 36.211 */
bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg, uint32_t nof_prb) {
if (cfg->beta_pucch > 0 &&
cfg->delta_pucch_shift > 0 && cfg->delta_pucch_shift < 4 &&
cfg->N_cs < 8 && (cfg->N_cs%cfg->delta_pucch_shift) == 0 &&
cfg->n_rb_2 < nof_prb) {
return true;
} else {
return false;
}
}
void srslte_pucch_cfg_default(srslte_pucch_cfg_t *cfg) {
cfg->beta_pucch = 1.0;
cfg->delta_pucch_shift = 1;
}
uint32_t get_N_sf(srslte_pucch_format_t format) {
@ -101,23 +114,23 @@ uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t
// 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 srslte_pucch_m(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, uint32_t n_pucch, srslte_cp_t cp) {
uint32_t m=0;
switch (cfg->format) {
switch (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;
if (n_pucch >= c*cfg->N_cs/cfg->delta_pucch_shift) {
m = (n_pucch-c*cfg->N_cs/cfg->delta_pucch_shift)/(c*SRSLTE_NRE/cfg->delta_pucch_shift)
+cfg->n_rb_2+(uint32_t)ceilf((float) cfg->N_cs/8);
}
break;
case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_2A:
case SRSLTE_PUCCH_FORMAT_2B:
m = cfg->n_pucch/SRSLTE_NRE;
m = n_pucch/SRSLTE_NRE;
break;
}
return m;
@ -146,20 +159,21 @@ int srslte_pucch_n_cs_cell(srslte_cell_t cell, uint32_t n_cs_cell[SRSLTE_NSLOTS_
/* 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_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
srslte_pucch_cfg_t *cfg,
srslte_pucch_cfg_t *cfg,
uint32_t n_pucch,
srslte_cp_t cp, bool is_dmrs,
uint32_t ns, uint32_t l,
uint32_t *n_oc_ptr, uint32_t *n_prime_ns)
{
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 = (n_pucch < c*cfg->N_cs/cfg->delta_pucch_shift)?cfg->N_cs:SRSLTE_NRE;
uint32_t n_prime = cfg->n_pucch;
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);
uint32_t n_prime = n_pucch;
if (n_pucch >= c*cfg->N_cs/cfg->delta_pucch_shift) {
n_prime = (n_pucch-c*cfg->N_cs/cfg->delta_pucch_shift)%(c*SRSLTE_NRE/cfg->delta_pucch_shift);
}
if (ns%2) {
if (cfg->n_pucch >= c*cfg->N_cs/cfg->delta_pucch_shift) {
if (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;
@ -191,27 +205,32 @@ float srslte_pucch_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NOR
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) {
static int pucch_put(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *output) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q && cfg && output) {
if (q && output) {
ret = SRSLTE_ERROR;
uint32_t nsymbols = SRSLTE_CP_ISNORM(q->cell.cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB;
// Determine m
uint32_t m = srslte_pucch_m(cfg, q->cell.cp);
uint32_t m = srslte_pucch_m(&q->pucch_cfg, format, n_pucch, q->cell.cp);
uint32_t N_sf = get_N_sf(cfg->format);
uint32_t N_sf = get_N_sf(format);
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));
if (n_prb < q->cell.nof_prb) {
for (uint32_t i=0;i<N_sf;i++) {
uint32_t l = get_pucch_symbol(i, format, q->cell.cp);
memcpy(&output[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
&q->z[i*SRSLTE_NRE+ns*N_sf*SRSLTE_NRE],
SRSLTE_NRE*sizeof(cf_t));
}
} else {
return SRSLTE_ERROR;
}
}
@ -229,6 +248,7 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
bzero(q, sizeof(srslte_pucch_t));
q->cell = cell;
srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
@ -248,12 +268,22 @@ void srslte_pucch_free(srslte_pucch_t *q) {
bzero(q, sizeof(srslte_pucch_t));
}
bool srslte_pucch_set_cfg(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg)
{
if (srslte_pucch_cfg_isvalid(cfg, q->cell.nof_prb)) {
memcpy(&q->pucch_cfg, cfg, sizeof(srslte_pucch_cfg_t));
return true;
} else {
return false;
}
}
static cf_t uci_encode_format1() {
return 1.0;
}
static cf_t uci_encode_format1a(uint8_t bit) {
return bit?1.0:-1.0;
return bit?-1.0:1.0;
}
static cf_t uci_encode_format1b(uint8_t bits[2]) {
@ -273,11 +303,11 @@ static cf_t uci_encode_format1b(uint8_t bits[2]) {
}
/* 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)
static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *d_0)
{
if (d_0) {
uint8_t tmp[2];
switch(cfg->format) {
switch(format) {
case SRSLTE_PUCCH_FORMAT_1:
*d_0 = uci_encode_format1();
break;
@ -288,6 +318,7 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, uint8_t bits
tmp[0] = bits[0];
tmp[1] = bits[1];
*d_0 = uci_encode_format1b(tmp);
break;
default:
fprintf(stderr, "PUCCH format 2 not supported\n");
return SRSLTE_ERROR;
@ -300,24 +331,23 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, uint8_t bits
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)
int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *sf_symbols)
{
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)) {
if (uci_mod_bits(q, format, bits, &d_0)) {
fprintf(stderr, "Error encoding PUCCH bits\n");
return SRSLTE_ERROR;
}
uint32_t N_sf=get_N_sf(cfg->format);
uint32_t N_sf=get_N_sf(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) {
if (q->pucch_cfg.group_hopping_en) {
f_gh = q->f_gh[ns];
}
uint32_t u = (f_gh + (q->cell.id%30))%30;
@ -325,27 +355,26 @@ int srslte_pucch_encode(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, uint32_t sf_
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 l = get_pucch_symbol(m, 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);
float alpha = srslte_pucch_alpha(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
float S_ns = 0;
uint32_t S_ns = 0;
if (n_prime_ns%2) {
S_ns = M_PI/2;
}
DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d\n", __real__ d_0, __imag__ d_0, alpha, n_oc, n_prime_ns);
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));
q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->pucch_cfg.beta_pucch*d_0*w_n_oc[n_oc%3][m]*cexpf(I*(q->tmp_arg[n]+alpha*n+S_ns));
}
}
}
if (pucch_put(q, cfg, sf_symbols)) {
if (pucch_put(q, format, n_pucch, sf_symbols)) {
fprintf(stderr, "Error putting PUCCH symbols\n");
return SRSLTE_ERROR;
}
ret = SRSLTE_SUCCESS;
}

@ -136,6 +136,22 @@ TARGET_LINK_LIBRARIES(pusch_test srslte)
BuildMex(MEXNAME ulsch_encode SOURCES ulsch_encode_test_mex.c LIBRARIES srslte srslte_mex)
BuildMex(MEXNAME pusch_encode SOURCES pusch_encode_test_mex.c LIBRARIES srslte srslte_mex)
ADD_TEST(pusch_test pusch_test)
########################################################################
# PUCCH TEST
########################################################################
ADD_EXECUTABLE(pucch_test pucch_test.c)
TARGET_LINK_LIBRARIES(pucch_test srslte)
ADD_TEST(pucch_test pucch_test -f 0)
ADD_TEST(pucch_test pucch_test -f 1)
ADD_TEST(pucch_test pucch_test -f 2)
BuildMex(MEXNAME pucch_encode SOURCES pucch_encode_test_mex.c LIBRARIES srslte srslte_mex)

@ -33,17 +33,14 @@
*/
#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
#define PUCCHCFG prhs[1]
#define ACK prhs[2]
#define NOF_INPUTS 3
void help()
{
mexErrMsgTxt
("sym=srslte_pusch_encode(ue, chs, trblkin, cqi, ri, ack)\n\n");
("[sym, sym_with_dmrs, subframe_all]=srslte_pucch_encode(ue, chs, ack)\n\n");
}
/* the gateway function */
@ -58,6 +55,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_cell_t cell;
bzero(&cell, sizeof(srslte_cell_t));
cell.nof_ports = 1;
cell.cp = SRSLTE_CP_NORM;
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
@ -66,157 +64,120 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Field NULRB not found in UE config\n");
return;
}
srslte_pusch_t pusch;
if (srslte_pusch_init(&pusch, cell)) {
srslte_pucch_t pucch;
if (srslte_pucch_init(&pucch, 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;
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");
uint32_t n_pucch;
if (mexutils_read_uint32_struct(PUCCHCFG, "ResourceIdx", &n_pucch)) {
mexErrMsgTxt("Field ResourceIdx not found in PUCCHCFG\n");
return;
}
if (srslte_harq_setup_ul(&harq_process, mcs, 0, sf_idx, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
srslte_pucch_cfg_t pucch_cfg;
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
pucch_cfg.beta_pucch = 1.0;
if (mexutils_read_uint32_struct(PUCCHCFG, "DeltaShift", &pucch_cfg.delta_pucch_shift)) {
mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\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");
if (mexutils_read_uint32_struct(PUCCHCFG, "CyclicShifts", &pucch_cfg.N_cs)) {
mexErrMsgTxt("Field CyclicShifts not found in PUCCHCFG\n");
return;
}
bzero(sf_symbols, sizeof(cf_t) * nof_re);
pucch_cfg.group_hopping_en = false;
char *hop = mexutils_get_char_struct(PUCCHCFG, "Hopping");
if (hop) {
if (!strcmp(hop, "Group")) {
pucch_cfg.group_hopping_en = true;
}
mxFree(hop);
}
uint8_t bits[SRSLTE_PUCCH_MAX_BITS];
float *bits_ptr;
int n = mexutils_read_f(ACK, &bits_ptr);
for (int i=0;i<n;i++) {
bits[i] = bits_ptr[i]>0?1:0;
}
free(bits_ptr);
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;
srslte_pucch_format_t format;
switch(n) {
case 0:
format = SRSLTE_PUCCH_FORMAT_1;
break;
case 1:
format = SRSLTE_PUCCH_FORMAT_1A;
break;
case 2:
format = SRSLTE_PUCCH_FORMAT_1B;
break;
default:
mexErrMsgTxt("Invalid number of bits in parameter ack\n");
return;
}
free(tmp);
uci_data.uci_ack_len = mexutils_read_uint8(ACK, &tmp);
if (uci_data.uci_ack_len > 0) {
uci_data.uci_ack = *tmp;
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!sf_symbols) {
return;
}
free(tmp);
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
srslte_pucch_set_cfg(&pucch, &pucch_cfg);
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;
if (srslte_pucch_encode(&pucch, format, n_pucch, 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);
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 (nlhs >= 1) {
mexutils_write_cf(pucch.z, &plhs[0], 96, 1);
}
if (rv > 0) {
if (srslte_harq_setup_ul(&harq_process, mcs, rv, sf_idx, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
if (nlhs >= 2) {
srslte_refsignal_ul_t pucch_dmrs;
if (srslte_refsignal_ul_init(&pucch_dmrs, cell)) {
mexErrMsgTxt("Error initiating PUCCH DMRS\n");
return;
}
r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols);
if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n");
cf_t *dmrs_pucch = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_NRE*3*2);
if (!dmrs_pucch) {
return;
}
bzero(dmrs_pucch, sizeof(cf_t)*SRSLTE_NRE*3*2);
if (!srslte_refsignal_ul_set_pucch_cfg(&pucch_dmrs, &pucch_cfg)) {
mexErrMsgTxt("Error setting PUCCH config\n");
return;
}
if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, format, n_pucch, sf_idx, dmrs_pucch)) {
mexErrMsgTxt("Error generating PUCCH DMRS\n");
return;
}
mexutils_write_cf(dmrs_pucch, &plhs[1], 2*3*SRSLTE_NRE, 1);
if (nlhs >= 3) {
if (srslte_refsignal_dmrs_pucch_put(&pucch_dmrs, format, n_pucch, dmrs_pucch, sf_symbols)) {
mexErrMsgTxt("Error generating PUCCH DMRS\n");
return;
}
mexutils_write_cf(sf_symbols, &plhs[2], 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));
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);
srslte_pucch_free(&pucch);
free(sf_symbols);
free(scfdma);
return;
}

@ -43,76 +43,37 @@ srslte_cell_t cell = {
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;
srslte_pucch_format_t format;
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("Usage: %s [csNnv] -f [format (0: Format 1 | 1: Format 1a | 2: Format 1b)]\n", prog);
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");
printf("\t-n nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-v [set verbose to debug, default none]\n");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "lcnfvmtsrLNFR")) != -1) {
while ((opt = getopt(argc, argv, "csNnvf")) != -1) {
switch(opt) {
case 'm':
case 'f':
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;
case 0:
format = SRSLTE_PUCCH_FORMAT_1;
break;
case 1:
format = SRSLTE_PUCCH_FORMAT_1A;
break;
case 2:
format = SRSLTE_PUCCH_FORMAT_1B;
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;
@ -130,141 +91,78 @@ void parse_args(int argc, char **argv) {
}
int main(int argc, char **argv) {
srslte_pusch_t pusch;
uint8_t *data = NULL;
srslte_pucch_t pucch;
srslte_pucch_cfg_t pucch_cfg;
srslte_refsignal_ul_t dmrs;
uint8_t bits[SRSLTE_PUCCH_MAX_BITS];
cf_t *sf_symbols = NULL;
cf_t pucch_dmrs[2*SRSLTE_NRE*3];
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)) {
if (srslte_pucch_init(&pucch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
srslte_pusch_set_rnti(&pusch, 1234);
if (srslte_harq_init(&harq_process, cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
if (srslte_refsignal_ul_init(&dmrs, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
printf("Encoding rv_idx=%d\n",rv_idx);
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
uint8_t tmp[20];
for (uint32_t i=0;i<20;i++) {
tmp[i] = 1;
for (int i=0;i<SRSLTE_PUCCH_MAX_BITS;i++) {
bits[i] = rand()%2;
}
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);
sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!sf_symbols) {
perror("malloc");
goto quit;
goto quit;
}
data = malloc(sizeof(uint8_t) * mcs.tbs);
if (!data) {
perror("malloc");
goto quit;
}
for (uint32_t d=1;d<=2;d++) {
for (uint32_t ncs=0;ncs<8;ncs+=d) {
for (uint32_t n_pucch=0;n_pucch<130;n_pucch++) {
INFO("n_pucch: %d, ncs: %d, d: %d\n", n_pucch, ncs, d);
pucch_cfg.beta_pucch = 1.0;
pucch_cfg.delta_pucch_shift = d;
pucch_cfg.group_hopping_en = false;
pucch_cfg.N_cs = ncs;
pucch_cfg.n_rb_2 = 0;
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);
if (!srslte_pucch_set_cfg(&pucch, &pucch_cfg)) {
fprintf(stderr, "Error setting PUCCH config\n");
goto quit;
}
if (srslte_pucch_encode(&pucch, format, n_pucch, subframe, bits, sf_symbols)) {
fprintf(stderr, "Error encoding PUCCH\n");
goto quit;
}
srslte_refsignal_ul_set_pucch_cfg(&dmrs, &pucch_cfg);
if (srslte_refsignal_dmrs_pucch_gen(&dmrs, format, n_pucch, subframe, pucch_dmrs)) {
fprintf(stderr, "Error encoding PUCCH\n");
goto quit;
}
if (srslte_refsignal_dmrs_pucch_put(&dmrs, format, n_pucch, pucch_dmrs, sf_symbols)) {
fprintf(stderr, "Error encoding PUCCH\n");
goto quit;
}
}
}
}
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);
srslte_pucch_free(&pucch);
srslte_refsignal_ul_free(&dmrs);
if (sf_symbols) {
free(sf_symbols);
}
if (data) {
free(data);
}
if (ret) {
printf("Error\n");
} else {

@ -33,14 +33,17 @@
*/
#define UECFG prhs[0]
#define PUCCHCFG prhs[1]
#define ACK prhs[2]
#define NOF_INPUTS 3
#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
("[subframe, subframe_with_dmrs]=srslte_pucch_encode(ue, chs, ack)\n\n");
("sym=srslte_pusch_encode(ue, chs, trblkin, cqi, ri, ack)\n\n");
}
/* the gateway function */
@ -55,7 +58,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_cell_t cell;
bzero(&cell, sizeof(srslte_cell_t));
cell.nof_ports = 1;
cell.cp = SRSLTE_CP_NORM;
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
@ -64,101 +66,157 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Field NULRB not found in UE config\n");
return;
}
srslte_pucch_t pucch;
if (srslte_pucch_init(&pucch, cell)) {
srslte_pusch_t pusch;
if (srslte_pusch_init(&pusch, cell)) {
mexErrMsgTxt("Error initiating PUSCH\n");
return;
}
uint32_t sf_idx = 0;
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_pucch_cfg_t pucch_cfg;
if (mexutils_read_uint32_struct(PUCCHCFG, "ResourceIdx", &pucch_cfg.n_pucch)) {
mexErrMsgTxt("Field ResourceIdx not found in PUCCHCFG\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;
}
if (mexutils_read_uint32_struct(PUCCHCFG, "DeltaShift", &pucch_cfg.delta_pucch_shift)) {
mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n");
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 (mexutils_read_uint32_struct(PUCCHCFG, "CyclicShifts", &pucch_cfg.N_cs)) {
mexErrMsgTxt("Field CyclicShifts not found in PUCCHCFG\n");
if (srslte_harq_setup_ul(&harq_process, mcs, 0, sf_idx, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
pucch_cfg.group_hopping_en = false;
char *hop = mexutils_get_char_struct(PUCCHCFG, "Hopping");
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];
float *bits_ptr;
int n = mexutils_read_f(ACK, &bits_ptr);
for (int i=0;i<n;i++) {
bits[i] = bits_ptr>0?1:0;
}
free(bits_ptr);
switch(n) {
case 0:
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;
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);
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, "OffsetCQI", &uci_data.I_offset_cqi)) {
uci_data.I_offset_cqi = 7;
}
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
if (srslte_pucch_encode(&pucch, &pucch_cfg, sf_idx, bits, sf_symbols)) {
mexErrMsgTxt("Error encoding PUCCH\n");
return;
if (mexutils_read_uint32_struct(PUSCHCFG, "OffsetRI", &uci_data.I_offset_ri)) {
uci_data.I_offset_ri = 2;
}
if (nlhs >= 1) {
mexutils_write_cf(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
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);
if (nlhs >= 2) {
srslte_refsignal_ul_t pucch_dmrs;
if (srslte_refsignal_ul_init(&pucch_dmrs, cell)) {
mexErrMsgTxt("Error initiating PUCCH DMRS\n");
return;
}
cf_t *dmrs_pucch = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_NRE*3);
if (!dmrs_pucch) {
return;
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;
}
if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, &pucch_cfg, sf_idx, dmrs_pucch)) {
mexErrMsgTxt("Error generating PUCCH DMRS\n");
return;
r = srslte_pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols);
if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n");
return;
}
if (srslte_refsignal_dmrs_pucch_put(&pucch_dmrs, &pucch_cfg, dmrs_pucch, sf_symbols)) {
mexErrMsgTxt("Error generating PUCCH DMRS\n");
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));
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));
srslte_pucch_free(&pucch);
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;
}

@ -153,7 +153,7 @@ void srslte_ue_ul_reset(srslte_ue_ul_t *q) {
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->dmrs_cfg, dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
srslte_refsignal_ul_set_pusch_cfg(&q->dmrs, dmrs_cfg);
srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg);
}
@ -206,13 +206,12 @@ 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
if (srslte_refsignal_dmrs_pusch_gen(&q->dmrs, &q->dmrs_cfg,
q->harq_process[0].ul_alloc.L_prb, sf_idx, q->refsignal))
if (srslte_refsignal_dmrs_pusch_gen(&q->dmrs, q->harq_process[0].ul_alloc.L_prb, sf_idx, q->refsignal))
{
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
return ret;
}
srslte_refsignal_dmrs_pusch_put(&q->dmrs, &q->dmrs_cfg, q->refsignal,
srslte_refsignal_dmrs_pusch_put(&q->dmrs, q->refsignal,
q->harq_process[0].ul_alloc.L_prb,
q->harq_process[0].ul_alloc.n_prb_tilde,
q->sf_symbols);

Loading…
Cancel
Save