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

master
ismagom 10 years ago
parent 571e45f48d
commit 7ad46244e8

@ -1,50 +1,66 @@
clear
ueConfig=struct('NCellID',2,'NULRB',6,'NSubframe',7,'CyclicPrefixUL','Normal','NTxAnts',1,'Hopping','Off');
ueConfig=struct('NCellID',50,'RNTI',11,'NULRB',6,'NSubframe',1,'CyclicPrefixUL','Normal','NTxAnts',1,'Hopping','Off');
pucchConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0,'ResourceSize',0);
addpath('../../debug/srslte/lib/phch/test')
format_str={'1','1a','1b','2','2a','2b'};
k=1;
for f=0:2
for n=0:130
for f=0:5
for n=0:7: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);
if (f >= 3)
nb=20;
nb_ack=f-3;
else
nb=f;
nb_ack=0;
end
bits=randi(2,nb,1)-1;
bits_ack=randi(2,nb_ack,1)-1;
fprintf('Testing PUCCH Format: %s, n_pucch=%d, DeltaShift=%d, CyclicShift=%d\n',format_str{f+1},n,d,ncs);
if (f >= 3)
[sym_mat, info]=ltePUCCH2(ueConfig,pucchConfig,bits);
idx=ltePUCCH2Indices(ueConfig,pucchConfig);
[dmrs_mat, info_dmrs]=ltePUCCH2DRS(ueConfig,pucchConfig,bits_ack);
idx_dmrs=ltePUCCH2DRSIndices(ueConfig,pucchConfig);
else
[sym_mat, info]=ltePUCCH1(ueConfig,pucchConfig,bits);
idx=ltePUCCH1Indices(ueConfig,pucchConfig);
[dmrs_mat, info_dmrs]=ltePUCCH1DRS(ueConfig,pucchConfig);
idx_dmrs=ltePUCCH1DRSIndices(ueConfig,pucchConfig);
end
subframe_mat = lteULResourceGrid(ueConfig);
subframe_mat(idx)=sym_mat;
subframe_mat(idx_dmrs)=dmrs_mat;
[sym, dmrs]=srslte_pucch_encode(ueConfig,pucchConfig,ack);
[sym, dmrs, subframe]=srslte_pucch_encode(ueConfig,pucchConfig,[bits; bits_ack]);
error_sym=mean(abs(sym-sym_mat));
error_dmrs=mean(abs(dmrs-dmrs_mat));
%error_sf=mean(abs(subframe_mat(:)-subframe_lib));
error_sf=mean(abs(subframe_mat(:)-subframe));
k=k+1;
if (error_sym > 1e-6)
if (error_sym > 1e-5)
disp(info)
plot(angle(sym)-angle(sym_mat))
plot(abs(sym-sym_mat))
error('Error in symbols');
end
if (error_dmrs > 1e-6)
if (error_dmrs > 1e-5)
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
if (error_sf > 1e-6)
disp(info)
plot(abs(subframe-subframe_mat(:)))
error('Error in subframe');
end
end
end
end

@ -105,9 +105,10 @@ SRSLTE_API void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q,
SRSLTE_API 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);
uint8_t pucch2_bits[2],
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
uint32_t sf_idx,
cf_t *r_pucch);
SRSLTE_API int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q,
srslte_pucch_format_t format,

@ -86,4 +86,8 @@ SRSLTE_API int srslte_sequence_pusch(srslte_sequence_t *seq,
uint32_t cell_id,
uint32_t len);
SRSLTE_API int srslte_sequence_pucch(srslte_sequence_t *seq,
uint16_t rnti,
uint32_t nslot,
uint32_t cell_id);
#endif

@ -38,10 +38,12 @@
#include "srslte/config.h"
#include "srslte/common/phy_common.h"
#include "srslte/common/sequence.h"
#include "srslte/modem/mod.h"
#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 5
#define SRSLTE_PUCCH_N_SEQ 12
#define SRSLTE_PUCCH_MAX_BITS 20
#define SRSLTE_PUCCH_MAX_SYMBOLS 120
typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_1 = 0,
@ -64,11 +66,16 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API {
srslte_cell_t cell;
srslte_pucch_cfg_t pucch_cfg;
srslte_sequence_t seq_f2[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_modem_table_t mod;
uint8_t bits_scram[SRSLTE_PUCCH_MAX_BITS];
cf_t d[SRSLTE_PUCCH_MAX_BITS/2];
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];
cf_t z[2*SRSLTE_PUCCH_N_SF_MAX*SRSLTE_PUCCH_N_SEQ];
cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS];
bool rnti_is_set;
}srslte_pucch_t;
@ -77,24 +84,34 @@ SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q,
SRSLTE_API void srslte_pucch_free(srslte_pucch_t *q);
SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q, srslte_pucch_cfg_t* cfg);
SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q,
srslte_pucch_cfg_t* cfg);
SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q,
uint16_t c_rnti);
SRSLTE_API int srslte_pucch_encode(srslte_pucch_t *q,
srslte_pucch_format_t format,
uint32_t n_pucch,
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
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,
uint32_t l,
uint32_t *n_oc,
uint32_t *n_prime_ns);
SRSLTE_API float srslte_pucch_alpha_format1(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,
uint32_t *n_prime_ns);
SRSLTE_API float srslte_pucch_alpha_format2(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
srslte_pucch_cfg_t *cfg,
uint32_t n_pucch,
uint32_t ns,
uint32_t l);
SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format,
@ -104,6 +121,9 @@ SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg,
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 int srslte_pucch_format2ab_mod_bits(srslte_pucch_format_t format,
uint8_t bits[2],
cf_t *d_10);
SRSLTE_API bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg,
uint32_t nof_prb);

@ -375,7 +375,7 @@ 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_format_t format, uint32_t n_pucch, uint32_t sf_idx, cf_t *r_pucch)
int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint8_t pucch_bits[2], uint32_t n_pucch, uint32_t sf_idx, cf_t *r_pucch)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q && r_pucch) {
@ -383,6 +383,11 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
uint32_t N_rs=get_N_rs(format, q->cell.cp);
cf_t z_m_1 = 1.0;
if (format == SRSLTE_PUCCH_FORMAT_2A || format == SRSLTE_PUCCH_FORMAT_2B) {
srslte_pucch_format2ab_mod_bits(format, pucch_bits, &z_m_1);
}
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
// Get group hopping number u
uint32_t f_gh=0;
@ -398,7 +403,12 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
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, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, NULL);
float alpha = 0.0;
if (format < SRSLTE_PUCCH_FORMAT_2) {
alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, NULL);
} else {
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l);
}
// Choose number of symbols and orthogonal sequence from Tables 5.5.2.2.1-1 to -3
float *w=NULL;
@ -424,10 +434,13 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
w=w_arg_pucch_format2_cpnorm;
break;
}
cf_t z_m = 1.0;
if (m == 1) {
z_m = z_m_1;
}
if (w) {
for (uint32_t n=0;n<SRSLTE_NRE;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));
r_pucch[(ns%2)*SRSLTE_NRE*N_rs+m*SRSLTE_NRE+n] = q->pucch_cfg.beta_pucch*z_m*cexpf(I*(w[m]+q->tmp_arg[n]+alpha*n));
}
} else {
return SRSLTE_ERROR;
@ -443,9 +456,10 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
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 && output) {
if (q && output && r_pucch) {
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(&q->pucch_cfg, format, n_pucch, q->cell.cp);
@ -458,8 +472,8 @@ int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_forma
}
for (uint32_t i=0;i<N_rs;i++) {
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)],
uint32_t l = get_pucch_dmrs_symbol(i, format, q->cell.cp);
memcpy(&output[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)],
&r_pucch[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE],
SRSLTE_NRE*sizeof(cf_t));
}

@ -38,6 +38,7 @@
#include "srslte/phch/pucch.h"
#include "srslte/common/sequence.h"
#include "srslte/common/phy_common.h"
#include "srslte/scrambling/scrambling.h"
#include "srslte/utils/debug.h"
#include "srslte/utils/vector.h"
@ -65,6 +66,15 @@ bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg, uint32_t nof_prb) {
}
}
// Verifies n_2_pucch as defined in 5.4
bool srslte_pucch_n2_isvalid(srslte_pucch_cfg_t *cfg, uint32_t n_pucch_2) {
if (n_pucch_2 < cfg->n_rb_2*SRSLTE_NRE+(uint32_t) ceilf((float) cfg->N_cs/8)*(SRSLTE_NRE-cfg->N_cs-2)) {
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;
@ -84,6 +94,25 @@ uint32_t get_N_sf(srslte_pucch_format_t format) {
return 0;
}
// Number of bits per subframe (M_bit) Table 5.4-1 36.211
uint32_t srslte_pucch_nbits_format(srslte_pucch_format_t format) {
switch(format) {
case SRSLTE_PUCCH_FORMAT_1:
return 0;
case SRSLTE_PUCCH_FORMAT_1A:
return 1;
case SRSLTE_PUCCH_FORMAT_1B:
return 2;
case SRSLTE_PUCCH_FORMAT_2:
return 20;
case SRSLTE_PUCCH_FORMAT_2A:
return 21;
case SRSLTE_PUCCH_FORMAT_2B:
return 22;
}
return 0;
}
uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp) {
switch (format) {
case SRSLTE_PUCCH_FORMAT_1:
@ -157,8 +186,8 @@ 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],
/* Calculates alpha for format 1/a/b according to 5.5.2.2.2 (is_dmrs=true) or 5.4.1 (is_dmrs=false) of 36.211 */
float srslte_pucch_alpha_format1(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,
@ -197,13 +226,40 @@ float srslte_pucch_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NOR
}
uint32_t n_cs = 0;
if (SRSLTE_CP_ISNORM(cp)) {
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+(n_oc%cfg->delta_pucch_shift))%N_prime)%12;
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+(n_oc%cfg->delta_pucch_shift))%N_prime)%SRSLTE_NRE;
} else {
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+n_oc/n_oc_div)%N_prime)%12;
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+n_oc/n_oc_div)%N_prime)%SRSLTE_NRE;
}
return 2 * M_PI * (n_cs) / 12;
return 2 * M_PI * (n_cs) / SRSLTE_NRE;
}
/* Calculates alpha for format 2/a/b according to 5.4.2 of 36.211 */
float srslte_pucch_alpha_format2(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
srslte_pucch_cfg_t *cfg,
uint32_t n_pucch,
uint32_t ns, uint32_t l)
{
uint32_t n_prime = n_pucch%SRSLTE_NRE;
if (n_pucch >= SRSLTE_NRE*cfg->n_rb_2) {
n_prime = (n_pucch + cfg->N_cs + 1)%SRSLTE_NRE;
}
if (ns%2) {
n_prime = (SRSLTE_NRE*(n_prime+1))%(SRSLTE_NRE+1)-1;
if (n_pucch >= SRSLTE_NRE*cfg->n_rb_2) {
int x = (SRSLTE_NRE-2-(int) n_pucch)%SRSLTE_NRE;
if (x >= 0) {
n_prime = (uint32_t) x;
} else {
n_prime = SRSLTE_NRE+x;
}
}
}
uint32_t n_cs = (n_cs_cell[ns][l]+n_prime)%SRSLTE_NRE;
DEBUG("n_pucch: %d, ns: %d, l: %d, n_prime: %d, n_cs: %d\n", n_pucch, ns, l, n_prime, n_cs);
return 2 * M_PI * (n_cs) / SRSLTE_NRE;
}
/* Map PUCCH symbols to physical resources according to 5.4.3 in 36.211 */
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;
@ -248,8 +304,14 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
bzero(q, sizeof(srslte_pucch_t));
q->cell = cell;
q->rnti_is_set = false;
srslte_pucch_cfg_default(&q->pucch_cfg);
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK, false)) {
return SRSLTE_ERROR;
}
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
return SRSLTE_ERROR;
@ -265,7 +327,25 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
}
void srslte_pucch_free(srslte_pucch_t *q) {
bzero(q, sizeof(srslte_pucch_t));
if (q->rnti_is_set) {
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
srslte_sequence_free(&q->seq_f2[sf_idx]);
}
}
srslte_modem_table_free(&q->mod);
bzero(q, sizeof(srslte_pucch_t));
}
int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti) {
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
// Precompute scrambling sequence for pucch format 2
if (srslte_sequence_pucch(&q->seq_f2[sf_idx], c_rnti, 2*sf_idx, q->cell.id)) {
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n");
return SRSLTE_ERROR;
}
}
q->rnti_is_set = true;
return SRSLTE_SUCCESS;
}
bool srslte_pucch_set_cfg(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg)
@ -302,27 +382,62 @@ static cf_t uci_encode_format1b(uint8_t bits[2]) {
}
}
/* Modulates bit 20 and 21 for Formats 2a and 2b as in Table 5.4.2-1 in 36.211 */
int srslte_pucch_format2ab_mod_bits(srslte_pucch_format_t format, uint8_t bits[2], cf_t *d_10) {
if (d_10) {
if (format == SRSLTE_PUCCH_FORMAT_2A) {
*d_10 = bits[0]?-1.0:1.0;
return SRSLTE_SUCCESS;
} else if (format == SRSLTE_PUCCH_FORMAT_2B) {
if (bits[0] == 0) {
if (bits[1] == 0) {
*d_10 = 1.0;
} else {
*d_10 = -I;
}
} else {
if (bits[1] == 0) {
*d_10 = I;
} else {
*d_10 = -1.0;
}
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR;
}
} else {
return SRSLTE_ERROR;
}
}
/* 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_format_t format, 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], uint32_t sf_idx)
{
if (d_0) {
uint8_t tmp[2];
switch(format) {
case SRSLTE_PUCCH_FORMAT_1:
*d_0 = uci_encode_format1();
break;
case SRSLTE_PUCCH_FORMAT_1A:
*d_0 = uci_encode_format1a(bits[0]);
break;
case SRSLTE_PUCCH_FORMAT_1B:
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;
}
uint8_t tmp[2];
switch(format) {
case SRSLTE_PUCCH_FORMAT_1:
q->d[0] = uci_encode_format1();
break;
case SRSLTE_PUCCH_FORMAT_1A:
q->d[0] = uci_encode_format1a(bits[0]);
break;
case SRSLTE_PUCCH_FORMAT_1B:
tmp[0] = bits[0];
tmp[1] = bits[1];
q->d[0] = uci_encode_format1b(tmp);
break;
case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_2A:
case SRSLTE_PUCCH_FORMAT_2B:
memcpy(q->bits_scram, bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
srslte_scrambling_b(&q->seq_f2[sf_idx], q->bits_scram);
srslte_mod_modulate(&q->mod, q->bits_scram, q->d, SRSLTE_PUCCH_MAX_BITS);
break;
default:
fprintf(stderr, "PUCCH format 2 not supported\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
@ -331,18 +446,24 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t
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_format_t format, uint32_t n_pucch, 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 &&
sf_symbols != NULL)
{
ret = SRSLTE_ERROR;
cf_t d_0 = 0;
if (uci_mod_bits(q, format, bits, &d_0)) {
if (format >= SRSLTE_PUCCH_FORMAT_2 && !q->rnti_is_set) {
fprintf(stderr, "Error encoding PUCCH: C-RNTI must be set before encoding PUCCH Format 2/2a/2b\n");
return SRSLTE_ERROR;
}
if (uci_mod_bits(q, format, bits, sf_idx)) {
fprintf(stderr, "Error encoding PUCCH bits\n");
return SRSLTE_ERROR;
}
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
@ -358,17 +479,27 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, uint32_
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, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
float S_ns = 0;
if (n_prime_ns%2) {
S_ns = M_PI/2;
float alpha=0;
if (format >= SRSLTE_PUCCH_FORMAT_2) {
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l);
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] = q->pucch_cfg.beta_pucch
*q->d[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n));
}
} else {
alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
float 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__ q->d[0], __imag__ q->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] = q->pucch_cfg.beta_pucch
*q->d[0]*w_n_oc[n_oc%3][m]*cexpf(I*(q->tmp_arg[n]+alpha*n+S_ns));
}
}
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] = 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, format, n_pucch, sf_symbols)) {

@ -66,7 +66,7 @@ int srslte_sequence_pdcch(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_
/**
* 36.211 6.3.1
*/
int srslte_sequence_pdsch(srslte_sequence_t *seq, unsigned short rnti, int q, uint32_t nslot, uint32_t cell_id, uint32_t len) {
int srslte_sequence_pdsch(srslte_sequence_t *seq, uint16_t rnti, int q, uint32_t nslot, uint32_t cell_id, uint32_t len) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, len, (rnti<<14) + (q<<13) + ((nslot/2)<<9) + cell_id);
}
@ -74,7 +74,15 @@ int srslte_sequence_pdsch(srslte_sequence_t *seq, unsigned short rnti, int q, ui
/**
* 36.211 5.3.1
*/
int srslte_sequence_pusch(srslte_sequence_t *seq, unsigned short rnti, uint32_t nslot, uint32_t cell_id, uint32_t len) {
int srslte_sequence_pusch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id, uint32_t len) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, len, (rnti<<14) + ((nslot/2)<<9) + cell_id);
}
/**
* 36.211 5.4.2
*/
int srslte_sequence_pucch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, 20, ((((nslot/2)+1)*(2*cell_id+1))<<16)+rnti);
}

@ -145,9 +145,7 @@ ADD_TEST(pusch_test pusch_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)
ADD_TEST(pucch_test pucch_test)
BuildMex(MEXNAME pucch_encode SOURCES pucch_encode_test_mex.c LIBRARIES srslte srslte_mex)

@ -75,6 +75,15 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Field NSubframe not found in UE config\n");
return;
}
uint32_t rnti;
if (mexutils_read_uint32_struct(UECFG, "RNTI", &rnti)) {
mexErrMsgTxt("Field NSubframe not found in UE config\n");
return;
}
if (srslte_pucch_set_crnti(&pucch, (uint16_t) rnti&0xffff)) {
mexErrMsgTxt("Error setting C-RNTI\n");
return;
}
uint32_t n_pucch;
if (mexutils_read_uint32_struct(PUCCHCFG, "ResourceIdx", &n_pucch)) {
mexErrMsgTxt("Field ResourceIdx not found in PUCCHCFG\n");
@ -101,12 +110,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
uint8_t bits[SRSLTE_PUCCH_MAX_BITS];
uint8_t pucch2_bits[2];
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) {
@ -119,10 +125,33 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
case 2:
format = SRSLTE_PUCCH_FORMAT_1B;
break;
case 20:
format = SRSLTE_PUCCH_FORMAT_2;
break;
case 21:
format = SRSLTE_PUCCH_FORMAT_2A;
break;
case 22:
format = SRSLTE_PUCCH_FORMAT_2B;
break;
default:
mexErrMsgTxt("Invalid number of bits in parameter ack\n");
return;
}
if (n > 20) {
n = 20;
}
for (int i=0;i<n;i++) {
bits[i] = bits_ptr[i]>0?1:0;
}
if (format == SRSLTE_PUCCH_FORMAT_2A) {
pucch2_bits[0] = bits_ptr[20];
}
if (format == SRSLTE_PUCCH_FORMAT_2B) {
pucch2_bits[0] = bits_ptr[20];
pucch2_bits[1] = bits_ptr[21];
}
free(bits_ptr);
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!sf_symbols) {
@ -138,7 +167,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
if (nlhs >= 1) {
mexutils_write_cf(pucch.z, &plhs[0], 96, 1);
uint32_t n_bits = 96;
if (format >= SRSLTE_PUCCH_FORMAT_2) {
n_bits = 120;
}
mexutils_write_cf(pucch.z, &plhs[0], n_bits, 1);
}
if (nlhs >= 2) {
@ -158,17 +191,21 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, format, n_pucch, sf_idx, dmrs_pucch)) {
if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, format, pucch2_bits, 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);
uint32_t n_rs = 3;
if (format >= SRSLTE_PUCCH_FORMAT_2) {
n_rs = 2;
}
mexutils_write_cf(dmrs_pucch, &plhs[1], 2*n_rs*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);
}

@ -44,10 +44,9 @@ srslte_cell_t cell = {
};
uint32_t subframe = 1;
srslte_pucch_format_t format;
void usage(char *prog) {
printf("Usage: %s [csNnv] -f [format (0: Format 1 | 1: Format 1a | 2: Format 1b)]\n", prog);
printf("Usage: %s [csNnv]\n", prog);
printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-s subframe [Default %d]\n", subframe);
printf("\t-n nof_prb [Default %d]\n", cell.nof_prb);
@ -56,21 +55,8 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "csNnvf")) != -1) {
while ((opt = getopt(argc, argv, "csNnv")) != -1) {
switch(opt) {
case 'f':
switch(atoi(argv[optind])) {
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;
@ -95,6 +81,7 @@ int main(int argc, char **argv) {
srslte_pucch_cfg_t pucch_cfg;
srslte_refsignal_ul_t dmrs;
uint8_t bits[SRSLTE_PUCCH_MAX_BITS];
uint8_t pucch2_bits[2];
cf_t *sf_symbols = NULL;
cf_t pucch_dmrs[2*SRSLTE_NRE*3];
int ret = -1;
@ -115,44 +102,55 @@ int main(int argc, char **argv) {
for (int i=0;i<SRSLTE_PUCCH_MAX_BITS;i++) {
bits[i] = rand()%2;
}
for (int i=0;i<2;i++) {
pucch2_bits[i] = rand()%2;
}
if (srslte_pucch_set_crnti(&pucch, 1234)) {
fprintf(stderr, "Error setting C-RNTI\n");
goto quit;
}
sf_symbols = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!sf_symbols) {
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;
if (!srslte_pucch_set_cfg(&pucch, &pucch_cfg)) {
fprintf(stderr, "Error setting PUCCH config\n");
goto quit;
srslte_pucch_format_t format;
for (format=0;format<=SRSLTE_PUCCH_FORMAT_2B;format++) {
for (uint32_t d=1;d<=3;d++) {
for (uint32_t ncs=0;ncs<8;ncs+=d) {
for (uint32_t n_pucch=1;n_pucch<130;n_pucch++) {
INFO("format %d, n_pucch: %d, ncs: %d, d: %d\n", format, 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;
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, pucch2_bits, 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_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;
}
}
}
}
}
ret = 0;

Loading…
Cancel
Save