mirror of https://github.com/PentHertz/srsLTE.git
PUCCH Formats 1/1a/1b verified with Matlab
This commit is contained in:
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;
|
||||
[sym, dmrs]=srslte_pucch_encode(ueConfig,pucchConfig,ack);
|
||||
|
||||
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)
|
||||
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;
|
||||
|
||||
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
|
||||
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;
|
||||
|
@ -147,19 +160,20 @@ 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,
|
||||
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,15 +205,16 @@ 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;
|
||||
|
@ -207,11 +222,15 @@ static int pucch_put(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg, cf_t *output) {
|
|||
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");
|
||||
uint32_t n_pucch;
|
||||
if (mexutils_read_uint32_struct(PUCCHCFG, "ResourceIdx", &n_pucch)) {
|
||||
mexErrMsgTxt("Field ResourceIdx not found in PUCCHCFG\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");
|
||||
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;
|
||||
}
|
||||
if (srslte_harq_setup_ul(&harq_process, mcs, 0, sf_idx, &prb_alloc)) {
|
||||
mexErrMsgTxt("Error configuring HARQ process\n");
|
||||
if (mexutils_read_uint32_struct(PUCCHCFG, "CyclicShifts", &pucch_cfg.N_cs)) {
|
||||
mexErrMsgTxt("Field CyclicShifts not found in PUCCHCFG\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);
|
||||
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_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;
|
||||
}
|
||||
|
||||
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
||||
if (!sf_symbols) {
|
||||
mexErrMsgTxt("malloc");
|
||||
return;
|
||||
}
|
||||
bzero(sf_symbols, sizeof(cf_t) * nof_re);
|
||||
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||
|
||||
srslte_pucch_set_cfg(&pucch, &pucch_cfg);
|
||||
|
||||
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");
|
||||
if (srslte_pucch_encode(&pucch, format, n_pucch, sf_idx, bits, sf_symbols)) {
|
||||
mexErrMsgTxt("Error encoding PUCCH\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);
|
||||
mexutils_write_cf(pucch.z, &plhs[0], 96, 1);
|
||||
}
|
||||
|
||||
if (nlhs >= 2) {
|
||||
mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1);
|
||||
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*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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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_pucch_set_cfg(&pucch, &pucch_cfg)) {
|
||||
fprintf(stderr, "Error setting PUCCH config\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_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 (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_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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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 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_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;
|
||||
}
|
||||
if (mexutils_read_uint32_struct(PUCCHCFG, "DeltaShift", &pucch_cfg.delta_pucch_shift)) {
|
||||
mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n");
|
||||
return;
|
||||
}
|
||||
if (mexutils_read_uint32_struct(PUCCHCFG, "CyclicShifts", &pucch_cfg.N_cs)) {
|
||||
mexErrMsgTxt("Field CyclicShifts not found in PUCCHCFG\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);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
mxFree(mod_str);
|
||||
|
||||
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;
|
||||
float *prbset = NULL;
|
||||
mxArray *p;
|
||||
p = mxGetField(PUSCHCFG, 0, "PRBSet");
|
||||
if (!p) {
|
||||
mexErrMsgTxt("Error field PRBSet not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
||||
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, 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");
|
||||
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(sf_symbols, &plhs[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
|
||||
mexutils_write_cf(scfdma, &plhs[0], SRSLTE_SF_LEN_PRB(cell.nof_prb), 1);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, &pucch_cfg, sf_idx, dmrs_pucch)) {
|
||||
mexErrMsgTxt("Error generating PUCCH DMRS\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);
|
||||
mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1);
|
||||
}
|
||||
|
||||
srslte_pucch_free(&pucch);
|
||||
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…
Reference in New Issue