ULSCH working all modes (with UCI) with matlab

This commit is contained in:
ismagom 2015-09-18 15:46:27 +02:00
parent ae99188360
commit 0a3bd81a28
14 changed files with 228 additions and 142 deletions

View File

@ -2,13 +2,12 @@ clear
ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1); ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0); puschConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0);
addpath('../../build/srslte/lib/phch/test') addpath('/home/ismael/work/srsLTE/debug/srslte/lib/phch/test')
cqilen=[0 20];
cqilen=0; mods={'QPSK','16QAM', '64QAM'};
mods={'QPSK'};
rvs=0; rvs=0;
betas=0; betas=[0 2.0 2.5 5.0, 20.0];
for p=1:100 for p=1:100
for i=0:26 for i=0:26
for m=1:length(mods) for m=1:length(mods)
@ -17,10 +16,11 @@ for p=1:100
for back=1:length(betas) for back=1:length(betas)
for c=1:length(cqilen) for c=1:length(cqilen)
puschConfig.PRBSet=(0:p-1)'; puschConfig.PRBSet=(0:p-1)';
TBs=lteTBS(length(puschConfig.PRBSet),i); TBs=lteTBS(length(puschConfig.PRBSet),i);
%TBs=24496; %TBs=256;
trblkin=randi(2,TBs,1)-1; %trblkin=randi(2,TBs,1)-1;
%trblkin=ones(1,TBs); trblkin=ones(1,TBs);
puschConfig.Modulation = mods{m}; puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r); puschConfig.RV = rvs(r);
@ -28,24 +28,22 @@ for p=1:100
puschConfig.BetaRI = betas(bri); puschConfig.BetaRI = betas(bri);
puschConfig.BetaACK = betas(back); puschConfig.BetaACK = betas(back);
if (betas(bri)>0) if (betas(bri)>0)
ri_bit=randi(2,1,1)-1; ri_bit=randi(2,1,1)-1;
else else
ri_bit=[]; ri_bit=[];
end end
if (betas(back)>0) if (betas(back)>0)
ack_bit=randi(2,1,1)-1; ack_bit=randi(2,1,1)-1;
else else
ack_bit=[]; ack_bit=[];
end end
if (cqilen(c)>0 || TBs>0) if (cqilen(c)>0 || TBs>0)
[lib]=srslte_ulsch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit); [lib]=srslte_ulsch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
lib(lib==192)=3;
lib(lib==48)=2;
[mat, info]=lteULSCH(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit,[]); [mat, info]=lteULSCH(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit,[]);
mat(mat==-2)=3; mat(mat==-2)=0;
mat(mat==-1)=2; mat(mat==-1)=0;
err=sum(abs(double(mat)-double(lib))); err=sum(abs(double(mat)-double(lib)));
if (err > 0) if (err > 0)
disp(err) disp(err)

View File

@ -42,6 +42,7 @@
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t *c; uint8_t *c;
uint8_t *c_bytes;
uint32_t len; uint32_t len;
} srslte_sequence_t; } srslte_sequence_t;

View File

@ -65,17 +65,19 @@ typedef struct SRSLTE_API {
/* buffers */ /* buffers */
uint8_t *cb_in; uint8_t *cb_in;
uint8_t *cb_temp;
void *cb_out; void *cb_out;
void *e; void *e;
uint8_t *temp_g_bits;
uint32_t *ul_interleaver;
srslte_uci_bit_t ack_ri_bits[12*288];
uint32_t nof_ri_ack_bits;
srslte_tcod_t encoder; srslte_tcod_t encoder;
srslte_tdec_t decoder; srslte_tdec_t decoder;
srslte_crc_t crc_tb; srslte_crc_t crc_tb;
srslte_crc_t crc_cb; srslte_crc_t crc_cb;
srslte_uci_cqi_pusch_t uci_cqi; srslte_uci_cqi_pusch_t uci_cqi;
srslte_uci_pos_t uci_pos;
} srslte_sch_t; } srslte_sch_t;

View File

@ -46,9 +46,6 @@
#define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13 #define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13
#define SRSLTE_UCI_CQI_CODED_PUCCH_B 20 #define SRSLTE_UCI_CQI_CODED_PUCCH_B 20
#define SRSLTE_UCI_ACK_RI_PLACEHOLDER_REPETITION 0xC0
#define SRSLTE_UCI_ACK_RI_PLACEHOLDER 0x30
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_crc_t crc; srslte_crc_t crc;
uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH]; uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH];
@ -67,10 +64,14 @@ typedef struct SRSLTE_API {
bool channel_selection; bool channel_selection;
} srslte_uci_data_t; } srslte_uci_data_t;
typedef enum {
UCI_BIT_1 = 0, UCI_BIT_0, UCI_BIT_REPETITION, UCI_BIT_PLACEHOLDER
} srslte_uci_bit_type_t;
typedef struct { typedef struct {
uint32_t idx; uint32_t position;
uint32_t pos[SRSLTE_UCI_MAX_CQI_LEN_PUSCH]; srslte_uci_bit_type_t type;
} srslte_uci_pos_t; } srslte_uci_bit_t;
SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q); SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q);
@ -89,19 +90,18 @@ SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data,
uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]); uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]);
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
srslte_uci_pos_t *pos,
uint8_t data, uint8_t data,
uint32_t O_cqi, uint32_t O_cqi,
float beta, float beta,
uint32_t H_prime_total, uint32_t H_prime_total,
uint8_t *q_bits); srslte_uci_bit_t *ri_bits);
SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t data, uint8_t data,
uint32_t O_cqi, uint32_t O_cqi,
float beta, float beta,
uint32_t H_prime_total, uint32_t H_prime_total,
uint8_t *q_bits); srslte_uci_bit_t *ri_bits);
#endif #endif

View File

@ -49,6 +49,14 @@ SRSLTE_API void srslte_scrambling_b_offset(srslte_sequence_t *s,
int offset, int offset,
int len); int len);
SRSLTE_API void srslte_scrambling_bytes(srslte_sequence_t *s,
uint8_t *data);
SRSLTE_API void srslte_scrambling_bytes_offset(srslte_sequence_t *s,
uint8_t *data,
int offset,
int len);
SRSLTE_API void srslte_scrambling_f(srslte_sequence_t *s, SRSLTE_API void srslte_scrambling_f(srslte_sequence_t *s,
float *data); float *data);

View File

@ -32,6 +32,7 @@
#include "srslte/common/sequence.h" #include "srslte/common/sequence.h"
#include "srslte/utils/vector.h" #include "srslte/utils/vector.h"
#include "srslte/utils/bit.h"
#define Nc 1600 #define Nc 1600
@ -81,18 +82,26 @@ int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
} }
q->len = len; q->len = len;
srslte_sequence_set_LTE_pr(q, seed); srslte_sequence_set_LTE_pr(q, seed);
srslte_bit_pack_vector(q->c, q->c_bytes, len);
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) { int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) {
if (q->c && (q->len != len)) { if (q->c && (q->len != len)) {
free(q->c); free(q->c);
if (q->c_bytes) {
free(q->c_bytes);
}
} }
if (!q->c) { if (!q->c) {
q->c = srslte_vec_malloc(len * sizeof(uint8_t)); q->c = srslte_vec_malloc(len * sizeof(uint8_t));
if (!q->c) { if (!q->c) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->c_bytes = srslte_vec_malloc(len * sizeof(uint8_t)/8);
if (!q->c_bytes) {
return SRSLTE_ERROR;
}
q->len = len; q->len = len;
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
@ -102,6 +111,9 @@ void srslte_sequence_free(srslte_sequence_t *q) {
if (q->c) { if (q->c) {
free(q->c); free(q->c);
} }
if (q->c_bytes) {
free(q->c_bytes);
}
bzero(q, sizeof(srslte_sequence_t)); bzero(q, sizeof(srslte_sequence_t));
} }

View File

@ -89,7 +89,7 @@ int srslte_cbsegm(srslte_cbsegm_t *s, uint32_t tbs) {
s->C1 = s->C - s->C2; s->C1 = s->C - s->C2;
} }
s->F = s->C1 * s->K1 + s->C2 * s->K2 - Bp; s->F = s->C1 * s->K1 + s->C2 * s->K2 - Bp;
printf("CB Segmentation: TBS: %d, C=%d, C+=%d K+=%d, C-=%d, K-=%d, F=%d, Bp=%d\n", INFO("CB Segmentation: TBS: %d, C=%d, C+=%d K+=%d, C-=%d, K-=%d, F=%d, Bp=%d\n",
tbs, s->C, s->C1, s->K1, s->C2, s->K2, s->F, Bp); tbs, s->C, s->C1, s->K1, s->C2, s->K2, s->F, Bp);
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }

View File

@ -546,12 +546,18 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs
// Correct UCI placeholder bits // Correct UCI placeholder bits
uint8_t *d = q->q; uint8_t *d = q->q;
for (int i = 0; i < q->dl_sch.uci_pos.idx; i++) { for (int i = 0; i < q->dl_sch.nof_ri_ack_bits; i++) {
if (d[q->dl_sch.uci_pos.pos[i]] & SRSLTE_UCI_ACK_RI_PLACEHOLDER) { if (q->dl_sch.ack_ri_bits[i].type == UCI_BIT_PLACEHOLDER) {
d[q->dl_sch.uci_pos.pos[i]] = 1; d[q->dl_sch.ack_ri_bits[i].position/8] |= (1<<(q->dl_sch.ack_ri_bits[i].position%8));
} else if (d[q->dl_sch.uci_pos.pos[i]] & SRSLTE_UCI_ACK_RI_PLACEHOLDER_REPETITION) { } else if (q->dl_sch.ack_ri_bits[i].type == UCI_BIT_REPETITION) {
if (q->dl_sch.uci_pos.pos[i] > 1) { if (q->dl_sch.ack_ri_bits[i].position > 1) {
d[q->dl_sch.uci_pos.pos[i]] = d[q->dl_sch.uci_pos.pos[i]-1]; uint32_t p=q->dl_sch.ack_ri_bits[i].position;
uint8_t bit = d[(p-1)/8] & (1<<((p-1)%8));
if (bit) {
d[p/8] |= 1<<(p%8);
} else {
d[p/8] &= ~(1<<(p%8));
}
} }
} }
} }

View File

@ -113,15 +113,20 @@ int srslte_sch_init(srslte_sch_t *q) {
if (!q->cb_in) { if (!q->cb_in) {
goto clean; goto clean;
} }
q->cb_temp = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_TCOD_MAX_LEN_CB+4);
if (!q->cb_temp) {
goto clean;
}
q->cb_out = srslte_vec_malloc(sizeof(float) * (3 * SRSLTE_TCOD_MAX_LEN_CB + 12)); q->cb_out = srslte_vec_malloc(sizeof(float) * (3 * SRSLTE_TCOD_MAX_LEN_CB + 12));
if (!q->cb_out) { if (!q->cb_out) {
goto clean; goto clean;
} }
q->temp_g_bits = srslte_vec_malloc(sizeof(uint8_t)*SRSLTE_MAX_PRB*12*12*12);
if (!q->temp_g_bits) {
goto clean;
}
bzero(q->temp_g_bits, SRSLTE_MAX_PRB*12*12*12);
q->ul_interleaver = srslte_vec_malloc(sizeof(uint32_t)*SRSLTE_MAX_PRB*12*12*12);
if (!q->ul_interleaver) {
goto clean;
}
if (srslte_uci_cqi_init(&q->uci_cqi)) { if (srslte_uci_cqi_init(&q->uci_cqi)) {
goto clean; goto clean;
} }
@ -139,12 +144,15 @@ void srslte_sch_free(srslte_sch_t *q) {
if (q->cb_in) { if (q->cb_in) {
free(q->cb_in); free(q->cb_in);
} }
if (q->cb_temp) {
free(q->cb_temp);
}
if (q->cb_out) { if (q->cb_out) {
free(q->cb_out); free(q->cb_out);
} }
if (q->temp_g_bits) {
free(q->temp_g_bits);
}
if (q->ul_interleaver) {
free(q->ul_interleaver);
}
srslte_tdec_free(&q->decoder); srslte_tdec_free(&q->decoder);
srslte_tcod_free(&q->encoder); srslte_tcod_free(&q->encoder);
srslte_uci_cqi_free(&q->uci_cqi); srslte_uci_cqi_free(&q->uci_cqi);
@ -161,15 +169,13 @@ uint32_t srslte_sch_last_noi(srslte_sch_t *q) {
} }
uint8_t temp[64*1024];
/* Encode a transport block according to 36.212 5.3.2 /* Encode a transport block according to 36.212 5.3.2
* *
*/ */
static int encode_tb(srslte_sch_t *q, static int encode_tb_off(srslte_sch_t *q,
srslte_softbuffer_tx_t *soft_buffer, srslte_cbsegm_t *cb_segm, srslte_softbuffer_tx_t *soft_buffer, srslte_cbsegm_t *cb_segm,
uint32_t Qm, uint32_t rv, uint32_t nof_e_bits, uint32_t Qm, uint32_t rv, uint32_t nof_e_bits,
uint8_t *data, uint8_t *e_bits) uint8_t *data, uint8_t *e_bits, uint32_t w_offset)
{ {
uint8_t parity[3] = {0, 0, 0}; uint8_t parity[3] = {0, 0, 0};
uint32_t par; uint32_t par;
@ -281,12 +287,11 @@ static int encode_tb(srslte_sch_t *q,
/* Rate matching */ /* Rate matching */
if (3*cb_len+12 < soft_buffer->buff_size) { if (3*cb_len+12 < soft_buffer->buff_size) {
if (srslte_rm_turbo_tx_lut(soft_buffer->buffer_b[i], q->cb_in, (uint8_t*) q->cb_out, &temp[wp/8], cblen_idx, n_e, wp%8, rv)) if (srslte_rm_turbo_tx_lut(soft_buffer->buffer_b[i], q->cb_in, (uint8_t*) q->cb_out, &e_bits[(wp+w_offset)/8], cblen_idx, n_e, (wp+w_offset)%8, rv))
{ {
fprintf(stderr, "Error in rate matching\n"); fprintf(stderr, "Error in rate matching\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_vec_fprint_byte(stdout, &temp[wp/8], (n_e-1)/8+1);
} else { } else {
fprintf(stderr, "Encoded CB length exceeds RM buffer (%d>%d)\n",3*cb_len+12,soft_buffer->buff_size); fprintf(stderr, "Encoded CB length exceeds RM buffer (%d>%d)\n",3*cb_len+12,soft_buffer->buff_size);
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -295,8 +300,6 @@ static int encode_tb(srslte_sch_t *q,
rp += rlen; rp += rlen;
wp += n_e; wp += n_e;
} }
srslte_bit_unpack_vector(temp, e_bits, nof_e_bits);
srslte_vec_fprint_b(stdout, e_bits, nof_e_bits);
INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp);
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -304,6 +307,16 @@ static int encode_tb(srslte_sch_t *q,
return ret; return ret;
} }
static int encode_tb(srslte_sch_t *q,
srslte_softbuffer_tx_t *soft_buffer, srslte_cbsegm_t *cb_segm,
uint32_t Qm, uint32_t rv, uint32_t nof_e_bits,
uint8_t *data, uint8_t *e_bits)
{
return encode_tb_off(q, soft_buffer, cb_segm, Qm, rv, nof_e_bits, data, e_bits, 0);
}
/* Decode a transport block according to 36.212 5.3.2 /* Decode a transport block according to 36.212 5.3.2
* *
*/ */
@ -498,34 +511,58 @@ int srslte_ulsch_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuf
e_bits, data); e_bits, data);
} }
/* UL-SCH channel interleaver according to 5.2.2.8 of 36.212 */ /* UL-SCH channel interleaver according to 5.2.2.8 of 36.212 */
void ulsch_interleave(srslte_uci_pos_t *q, uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total,
uint32_t N_pusch_symbs, uint8_t *q_bits) uint32_t N_pusch_symbs, uint8_t *q_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits,
uint32_t *interleaver_buffer, uint8_t *temp_buffer, uint32_t buffer_sz)
{ {
uint32_t rows = H_prime_total/N_pusch_symbs; uint32_t rows = H_prime_total/N_pusch_symbs;
uint32_t cols = N_pusch_symbs; uint32_t cols = N_pusch_symbs;
uint32_t idx = 0; // Prepare ri_bits for fast search using temp_buffer
for(uint32_t j=0; j<rows; j++) { if (nof_ri_bits > 0) {
for(uint32_t i=0; i<cols; i++) { for (uint32_t i=0;i<nof_ri_bits;i++) {
for(uint32_t k=0; k<Qm; k++) { if (ri_bits[i].position < buffer_sz) {
if (q_bits[j*Qm + i*rows*Qm + k] >= 10) { temp_buffer[ri_bits[i].position] = 1;
q_bits[j*Qm + i*rows*Qm + k] -= 10; } else {
q->pos[q->idx%SRSLTE_UCI_MAX_CQI_LEN_PUSCH] = j*Qm + i*rows*Qm + k; fprintf(stderr, "Error computing ULSCH interleaver RI bits. Position %d exceeds buffer size %d\n", ri_bits[i].position, buffer_sz);
q->idx++;
if (q->idx >= SRSLTE_UCI_MAX_CQI_LEN_PUSCH) {
fprintf(stderr, "Error number of UCI bits exceeds SRSLTE_UCI_MAX_CQI_LEN_PUSCH\n");
}
} else {
q_bits[j*Qm + i*rows*Qm + k] = g_bits[idx];
idx++;
}
} }
} }
} }
/* Compute the interleaving function on-the-fly, because it depends on number of RI bits
* Profiling show that the computation of this matrix is neglegible.
*/
uint32_t idx = 0;
for(uint32_t j=0; j<rows; j++) {
for(uint32_t i=0; i<cols; i++) {
for(uint32_t k=0; k<Qm; k++) {
if (temp_buffer[j*Qm + i*rows*Qm + k]) {
interleaver_buffer[j*Qm + i*rows*Qm + k] = 0;
} else {
if (j*Qm + i*rows*Qm + k < buffer_sz) {
interleaver_buffer[j*Qm + i*rows*Qm + k] = idx;
idx++;
} else {
fprintf(stderr, "Error computing ULSCH interleaver. Position %d exceeds buffer size %d\n", j*Qm + i*rows*Qm + k, buffer_sz);
}
}
}
}
}
srslte_bit_interleave(g_bits, q_bits, interleaver_buffer, H_prime_total*Qm);
// Reset temp_buffer because will be reused next time
if (nof_ri_bits > 0) {
for (uint32_t i=0;i<nof_ri_bits;i++) {
if (ri_bits[i].position < buffer_sz) {
temp_buffer[ri_bits[i].position] = 0;
} else {
fprintf(stderr, "Error computing ULSCH interleaver RI bits. Position %d exceeds buffer size %d\n", ri_bits[i].position, buffer_sz);
}
}
}
} }
int srslte_ulsch_encode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, int srslte_ulsch_encode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
@ -551,15 +588,13 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
uint32_t nb_q = cfg->nbits.nof_bits; uint32_t nb_q = cfg->nbits.nof_bits;
uint32_t Qm = cfg->grant.Qm; uint32_t Qm = cfg->grant.Qm;
bzero(q_bits, sizeof(uint8_t) * nb_q);
// Encode RI // Encode RI
if (uci_data.uci_ri_len > 0) { if (uci_data.uci_ri_len > 0) {
float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri]; float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri];
if (cfg->cb_segm.tbs == 0) { if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
} }
ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits); ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -571,43 +606,65 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, cfg, ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, cfg,
uci_data.uci_cqi, uci_data.uci_cqi_len, uci_data.uci_cqi, uci_data.uci_cqi_len,
beta_cqi_offset[cfg->uci_cfg.I_offset_cqi], beta_cqi_offset[cfg->uci_cfg.I_offset_cqi],
Q_prime_ri, g_bits); Q_prime_ri, q->temp_g_bits);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
Q_prime_cqi = (uint32_t) ret; Q_prime_cqi = (uint32_t) ret;
srslte_bit_pack_vector(q->temp_g_bits, g_bits, Q_prime_cqi*Qm);
// Reset the buffer because will be reused in ulsch_interleave
bzero(q->temp_g_bits, Q_prime_cqi*Qm);
} }
e_offset += Q_prime_cqi*Qm; e_offset += Q_prime_cqi*Qm;
// Encode UL-SCH // Encode UL-SCH
if (cfg->cb_segm.tbs > 0) { if (cfg->cb_segm.tbs > 0) {
uint32_t G = nb_q/Qm - Q_prime_ri - Q_prime_cqi; uint32_t G = nb_q/Qm - Q_prime_ri - Q_prime_cqi;
ret = encode_tb(q, softbuffer, &cfg->cb_segm, ret = encode_tb_off(q, softbuffer, &cfg->cb_segm,
Qm, cfg->rv, G*Qm, Qm, cfg->rv, G*Qm,
data, &g_bits[e_offset]); data, &g_bits[e_offset/8], e_offset%8);
if (ret) { if (ret) {
return ret; return ret;
} }
} }
//srslte_bit_unpack_vector(g_bits, kk, nb_q);
//srslte_vec_fprint_b(stdout, kk, nb_q);
// Interleave UL-SCH (and RI and CQI) // Interleave UL-SCH (and RI and CQI)
q->uci_pos.idx=0; ulsch_interleave(g_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits, q->ack_ri_bits, Q_prime_ri*Qm,
ulsch_interleave(&q->uci_pos, g_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits); q->ul_interleaver, q->temp_g_bits, SRSLTE_MAX_PRB*12*12*12);
// Encode (and interleave) ACK // Encode (and interleave) ACK
if (uci_data.uci_ack_len > 0) { if (uci_data.uci_ack_len > 0) {
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack]; float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
if (cfg->cb_segm.tbs == 0) { if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
} }
ret = srslte_uci_encode_ack(cfg, &q->uci_pos, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits); ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, &q->ack_ri_bits[Q_prime_ri*Qm]);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
Q_prime_ack = (uint32_t) ret; Q_prime_ack = (uint32_t) ret;
} }
q->nof_ri_ack_bits = (Q_prime_ack+Q_prime_ri)*Qm;
for (uint32_t i=0;i<q->nof_ri_ack_bits;i++) {
uint32_t p = q->ack_ri_bits[i].position;
if (p < nb_q) {
if (q->ack_ri_bits[i].type == UCI_BIT_1) {
q_bits[p/8] |= (1<<(7-p%8));
} else {
q_bits[p/8] &= ~(1<<(7-p%8));
}
} else {
fprintf(stderr, "Invalid RI/ACK bit position %d. Max bits=%d\n", p, nb_q);
}
}
INFO("Q_prime_ack=%d, Q_prime_cqi=%d, Q_prime_ri=%d\n",Q_prime_ack, Q_prime_cqi, Q_prime_ri); INFO("Q_prime_ack=%d, Q_prime_cqi=%d, Q_prime_ri=%d\n",Q_prime_ack, Q_prime_cqi, Q_prime_ri);
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;

View File

@ -241,10 +241,10 @@ int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, srslte_pusch_cfg_t *c
} }
} }
/* Inserts UCI-ACK bits into the correct positions in the g buffer before interleaving */ /* Generates UCI-ACK bits and computes position in q bits */
static int uci_ulsch_interleave_ack(srslte_uci_pos_t *q, uint8_t ack_coded_bits[6], uint32_t ack_q_bit_idx, static int uci_ulsch_interleave_ack(srslte_uci_bit_type_t ack_coded_bits[6], uint32_t ack_q_bit_idx,
uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp,
uint8_t *q_bits) { srslte_uci_bit_t *ack_bits) {
const uint32_t ack_column_set_norm[4] = {2, 3, 8, 9}; const uint32_t ack_column_set_norm[4] = {2, 3, 8, 9};
const uint32_t ack_column_set_ext[4] = {1, 2, 6, 7}; const uint32_t ack_column_set_ext[4] = {1, 2, 6, 7};
@ -255,14 +255,8 @@ static int uci_ulsch_interleave_ack(srslte_uci_pos_t *q, uint8_t ack_coded_bits[
uint32_t colidx = (3*ack_q_bit_idx)%4; uint32_t colidx = (3*ack_q_bit_idx)%4;
uint32_t col = SRSLTE_CP_ISNORM(cp)?ack_column_set_norm[colidx]:ack_column_set_ext[colidx]; uint32_t col = SRSLTE_CP_ISNORM(cp)?ack_column_set_norm[colidx]:ack_column_set_ext[colidx];
for(uint32_t k=0; k<Qm; k++) { for(uint32_t k=0; k<Qm; k++) {
q_bits[row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k] = ack_coded_bits[k]; ack_bits[k].position = row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k;
ack_bits[k].type = ack_coded_bits[k];
// Save position for placeholder bits
q->pos[q->idx%SRSLTE_UCI_MAX_CQI_LEN_PUSCH] = row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k;
q->idx++;
if (q->idx >= SRSLTE_UCI_MAX_CQI_LEN_PUSCH) {
fprintf(stderr, "Error number of UCI bits exceeds SRSLTE_UCI_MAX_CQI_LEN_PUSCH\n");
}
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} else { } else {
@ -273,9 +267,9 @@ static int uci_ulsch_interleave_ack(srslte_uci_pos_t *q, uint8_t ack_coded_bits[
} }
/* Inserts UCI-RI bits into the correct positions in the g buffer before interleaving */ /* Inserts UCI-RI bits into the correct positions in the g buffer before interleaving */
static int uci_ulsch_interleave_ri(uint8_t ri_coded_bits[6], uint32_t ri_q_bit_idx, static int uci_ulsch_interleave_ri(srslte_uci_bit_type_t ri_coded_bits[6], uint32_t ri_q_bit_idx,
uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp,
uint8_t *q_bits) { srslte_uci_bit_t *ri_bits) {
static uint32_t ri_column_set_norm[4] = {1, 4, 7, 10}; static uint32_t ri_column_set_norm[4] = {1, 4, 7, 10};
static uint32_t ri_column_set_ext[4] = {0, 3, 5, 8}; static uint32_t ri_column_set_ext[4] = {0, 3, 5, 8};
@ -286,7 +280,8 @@ static int uci_ulsch_interleave_ri(uint8_t ri_coded_bits[6], uint32_t ri_q_bit_i
uint32_t col = SRSLTE_CP_ISNORM(cp)?ri_column_set_norm[colidx]:ri_column_set_ext[colidx]; uint32_t col = SRSLTE_CP_ISNORM(cp)?ri_column_set_norm[colidx]:ri_column_set_ext[colidx];
for(uint32_t k=0; k<Qm; k++) { for(uint32_t k=0; k<Qm; k++) {
q_bits[row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k] = 10+ri_coded_bits[k]; ri_bits[k].position = row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k;
ri_bits[k].type = ri_coded_bits[k];
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} else { } else {
@ -323,21 +318,20 @@ static uint32_t Q_prime_ri_ack(srslte_pusch_cfg_t *cfg,
return Q_prime; return Q_prime;
} }
static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Qm) { static void encode_ri_ack(uint8_t data, srslte_uci_bit_type_t q_encoded_bits[6], uint8_t Qm) {
q_encoded_bits[0] = data; q_encoded_bits[0] = data?UCI_BIT_1:UCI_BIT_0;
q_encoded_bits[1] = SRSLTE_UCI_ACK_RI_PLACEHOLDER_REPETITION; q_encoded_bits[1] = UCI_BIT_REPETITION;
for (uint32_t i=2;i<Qm;i++) { for (uint32_t i=2;i<Qm;i++) {
q_encoded_bits[i] = SRSLTE_UCI_ACK_RI_PLACEHOLDER; q_encoded_bits[i] = UCI_BIT_PLACEHOLDER;
} }
} }
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212 /* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ * Currently only supporting 1-bit HARQ
*/ */
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, srslte_uci_pos_t *pos, int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t data,
uint8_t data,
uint32_t O_cqi, float beta, uint32_t H_prime_total, uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits) srslte_uci_bit_t *ack_bits)
{ {
if (beta < 0) { if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n"); fprintf(stderr, "Error beta is reserved\n");
@ -345,12 +339,12 @@ int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, srslte_uci_pos_t *pos,
} }
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
uint8_t q_encoded_bits[6]; srslte_uci_bit_type_t q_encoded_bits[6];
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm); encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) { for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ack(pos, q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, q_bits); uci_ulsch_interleave_ack(q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
} }
return (int) Qprime; return (int) Qprime;
@ -363,19 +357,19 @@ int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, srslte_uci_pos_t *pos,
int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t data, uint8_t data,
uint32_t O_cqi, float beta, uint32_t H_prime_total, uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits) srslte_uci_bit_t *ri_bits)
{ {
if (beta < 0) { if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n"); fprintf(stderr, "Error beta is reserved\n");
return -1; return -1;
} }
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
uint8_t q_encoded_bits[6]; srslte_uci_bit_type_t q_encoded_bits[6];
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm); encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) { for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ri(q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, q_bits); uci_ulsch_interleave_ri(q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
} }
return (int) Qprime; return (int) Qprime;

View File

@ -167,7 +167,7 @@ int main(int argc, char **argv) {
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_data.uci_cqi_len = 0; uci_data.uci_cqi_len = 20;
uci_data.uci_ri_len = 0; uci_data.uci_ri_len = 0;
uci_data.uci_ack_len = 0; uci_data.uci_ack_len = 0;
@ -202,7 +202,7 @@ int main(int argc, char **argv) {
data[i] = 1; data[i] = 1;
} }
if (srslte_softbuffer_tx_init(&softbuffer, 4*cell.nof_prb)) { if (srslte_softbuffer_tx_init(&softbuffer, 100)) {
fprintf(stderr, "Error initiating soft buffer\n"); fprintf(stderr, "Error initiating soft buffer\n");
goto quit; goto quit;
} }

View File

@ -69,7 +69,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cell.id=1; cell.id=1;
cell.cp=SRSLTE_CP_NORM; cell.cp=SRSLTE_CP_NORM;
srslte_verbose = SRSLTE_VERBOSE_INFO; srslte_verbose = SRSLTE_VERBOSE_NONE;
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) { if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
mexErrMsgTxt("Error initiating HARQ\n"); mexErrMsgTxt("Error initiating HARQ\n");
@ -175,11 +175,15 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
uint8_t *q_bits = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t)); uint8_t *q_bits = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t)/8);
if (!q_bits) { if (!q_bits) {
return; return;
} }
uint8_t *g_bits = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t)); uint8_t *q_bits_unpacked = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t));
if (!q_bits_unpacked) {
return;
}
uint8_t *g_bits = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t)/8);
if (!g_bits) { if (!g_bits) {
return; return;
} }
@ -196,9 +200,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
} }
srslte_bit_unpack_vector(q_bits, q_bits_unpacked, cfg.nbits.nof_bits);
if (nlhs >= 1) { if (nlhs >= 1) {
mexutils_write_uint8(q_bits, &plhs[0], cfg.nbits.nof_bits, 1); mexutils_write_uint8(q_bits_unpacked, &plhs[0], cfg.nbits.nof_bits, 1);
} }
srslte_sch_free(&ulsch); srslte_sch_free(&ulsch);
@ -206,6 +212,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
free(trblkin); free(trblkin);
free(g_bits); free(g_bits);
free(q_bits_unpacked);
free(q_bits); free(q_bits);

View File

@ -58,37 +58,47 @@ void srslte_scrambling_c_offset(srslte_sequence_t *s, cf_t *data, int offset, in
} }
} }
void srslte_scrambling_b(srslte_sequence_t *s, uint8_t *data) { void scrambling_b(uint8_t *c, uint8_t *data, int offset, int len) {
srslte_scrambling_b_offset(s, data, 0, s->len);
}
void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
int i; int i;
assert (len + offset <= s->len);
// Do XOR on a word basis // Do XOR on a word basis
if (!(len%8)) { if (!(len%8)) {
uint64_t *x = (uint64_t*) data; uint64_t *x = (uint64_t*) data;
uint64_t *y = (uint64_t*) &s->c[offset]; uint64_t *y = (uint64_t*) &c[offset];
for (int i=0;i<len/8;i++) { for (int i=0;i<len/8;i++) {
x[i] = (x[i] ^ y[i]); x[i] = (x[i] ^ y[i]);
} }
} else if (!(len%4)) { } else if (!(len%4)) {
uint32_t *x = (uint32_t*) data; uint32_t *x = (uint32_t*) data;
uint32_t *y = (uint32_t*) &s->c[offset]; uint32_t *y = (uint32_t*) &c[offset];
for (int i=0;i<len/4;i++) { for (int i=0;i<len/4;i++) {
x[i] = (x[i] ^ y[i]); x[i] = (x[i] ^ y[i]);
} }
} else if (!(len%2)) { } else if (!(len%2)) {
uint16_t *x = (uint16_t*) data; uint16_t *x = (uint16_t*) data;
uint16_t *y = (uint16_t*) &s->c[offset]; uint16_t *y = (uint16_t*) &c[offset];
for (int i=0;i<len/2;i++) { for (int i=0;i<len/2;i++) {
x[i] = (x[i] ^ y[i]); x[i] = (x[i] ^ y[i]);
} }
} else { } else {
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
data[i] = (data[i] + s->c[i + offset]) % 2; data[i] = (data[i] ^ c[i + offset]);
} }
} }
} }
void srslte_scrambling_b(srslte_sequence_t *s, uint8_t *data) {
scrambling_b(s->c, data, 0, s->len);
}
void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
scrambling_b(s->c, data, offset, len);
}
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data) {
scrambling_b(s->c_bytes, data, 0, s->len);
}
void srslte_scrambling_bytes_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
scrambling_b(s->c_bytes, data, offset, len);
}

View File

@ -212,23 +212,14 @@ bitarray_copy(const unsigned char *src_org, int src_offset, int src_len,
void srslte_bit_copy(uint8_t *dst, uint32_t dst_offset, uint8_t *src, uint32_t src_offset, uint32_t nof_bits) void srslte_bit_copy(uint8_t *dst, uint32_t dst_offset, uint8_t *src, uint32_t src_offset, uint32_t nof_bits)
{ {
static const uint8_t mask_src[] =
{ 0x00, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
static const uint8_t mask_dst[] = static const uint8_t mask_dst[] =
{ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
if ((dst_offset%8) == (src_offset%8)) { if ((dst_offset%8) == 0 && (src_offset%8) == 0) {
if (src_offset%8) {
// copy 1st word
dst[dst_offset/8] &= 0xf0;
dst[dst_offset/8] |= (src[src_offset/8] & mask_src[src_offset%8]);
dst_offset+=(src_offset%8);
src_offset+=(src_offset%8);
}
// copy rest of words // copy rest of words
memcpy(&dst[dst_offset/8], &src[src_offset/8], nof_bits/8); memcpy(&dst[dst_offset/8], &src[src_offset/8], nof_bits/8);
// copy last word // copy last word
if ((src_offset%8+nof_bits)%8) { if (nof_bits%8) {
dst[dst_offset/8+nof_bits/8] = src[src_offset/8+nof_bits/8] & mask_dst[(src_offset%8+nof_bits)%8]; dst[dst_offset/8+nof_bits/8] = src[src_offset/8+nof_bits/8] & mask_dst[nof_bits%8];
} }
} else { } else {
bitarray_copy(src, src_offset, nof_bits, dst, dst_offset); bitarray_copy(src, src_offset, nof_bits, dst, dst_offset);