ULSCH working all modes (with UCI) with matlab

master
ismagom 9 years ago
parent ae99188360
commit 0a3bd81a28

@ -2,13 +2,12 @@ clear
ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1);
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;
mods={'QPSK'};
cqilen=[0 20];
mods={'QPSK','16QAM', '64QAM'};
rvs=0;
betas=0;
betas=[0 2.0 2.5 5.0, 20.0];
for p=1:100
for i=0:26
for m=1:length(mods)
@ -17,10 +16,11 @@ for p=1:100
for back=1:length(betas)
for c=1:length(cqilen)
puschConfig.PRBSet=(0:p-1)';
TBs=lteTBS(length(puschConfig.PRBSet),i);
%TBs=24496;
trblkin=randi(2,TBs,1)-1;
%trblkin=ones(1,TBs);
%TBs=256;
%trblkin=randi(2,TBs,1)-1;
trblkin=ones(1,TBs);
puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r);
@ -28,24 +28,22 @@ for p=1:100
puschConfig.BetaRI = betas(bri);
puschConfig.BetaACK = 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 (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>0)
[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(mat==-2)=3;
mat(mat==-1)=2;
mat(mat==-2)=0;
mat(mat==-1)=0;
err=sum(abs(double(mat)-double(lib)));
if (err > 0)
disp(err)

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

@ -65,17 +65,19 @@ typedef struct SRSLTE_API {
/* buffers */
uint8_t *cb_in;
uint8_t *cb_temp;
void *cb_out;
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_tdec_t decoder;
srslte_crc_t crc_tb;
srslte_crc_t crc_cb;
srslte_uci_cqi_pusch_t uci_cqi;
srslte_uci_pos_t uci_pos;
srslte_uci_cqi_pusch_t uci_cqi;
} srslte_sch_t;

@ -46,9 +46,6 @@
#define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13
#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 {
srslte_crc_t crc;
uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH];
@ -67,10 +64,14 @@ typedef struct SRSLTE_API {
bool channel_selection;
} 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 {
uint32_t idx;
uint32_t pos[SRSLTE_UCI_MAX_CQI_LEN_PUSCH];
} srslte_uci_pos_t;
uint32_t position;
srslte_uci_bit_type_t type;
} srslte_uci_bit_t;
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]);
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
srslte_uci_pos_t *pos,
uint8_t data,
uint32_t O_cqi,
float beta,
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,
uint8_t data,
uint32_t O_cqi,
float beta,
uint32_t H_prime_total,
uint8_t *q_bits);
srslte_uci_bit_t *ri_bits);
#endif

@ -49,6 +49,14 @@ SRSLTE_API void srslte_scrambling_b_offset(srslte_sequence_t *s,
int offset,
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,
float *data);

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

@ -89,7 +89,7 @@ int srslte_cbsegm(srslte_cbsegm_t *s, uint32_t tbs) {
s->C1 = s->C - s->C2;
}
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);
ret = SRSLTE_SUCCESS;
}

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

@ -113,15 +113,20 @@ int srslte_sch_init(srslte_sch_t *q) {
if (!q->cb_in) {
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));
if (!q->cb_out) {
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)) {
goto clean;
}
@ -139,12 +144,15 @@ void srslte_sch_free(srslte_sch_t *q) {
if (q->cb_in) {
free(q->cb_in);
}
if (q->cb_temp) {
free(q->cb_temp);
}
if (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_tcod_free(&q->encoder);
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
*
*/
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,
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};
uint32_t par;
@ -281,12 +287,11 @@ static int encode_tb(srslte_sch_t *q,
/* Rate matching */
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");
return SRSLTE_ERROR;
}
srslte_vec_fprint_byte(stdout, &temp[wp/8], (n_e-1)/8+1);
} else {
fprintf(stderr, "Encoded CB length exceeds RM buffer (%d>%d)\n",3*cb_len+12,soft_buffer->buff_size);
return SRSLTE_ERROR;
@ -295,8 +300,6 @@ static int encode_tb(srslte_sch_t *q,
rp += rlen;
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);
ret = SRSLTE_SUCCESS;
@ -304,6 +307,16 @@ static int encode_tb(srslte_sch_t *q,
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
*
*/
@ -498,34 +511,58 @@ int srslte_ulsch_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuf
e_bits, data);
}
/* 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,
uint32_t N_pusch_symbs, uint8_t *q_bits)
void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total,
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 cols = N_pusch_symbs;
// Prepare ri_bits for fast search using temp_buffer
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] = 1;
} else {
fprintf(stderr, "Error computing ULSCH interleaver RI bits. Position %d exceeds buffer size %d\n", ri_bits[i].position, buffer_sz);
}
}
}
/* 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 (q_bits[j*Qm + i*rows*Qm + k] >= 10) {
q_bits[j*Qm + i*rows*Qm + k] -= 10;
q->pos[q->idx%SRSLTE_UCI_MAX_CQI_LEN_PUSCH] = j*Qm + i*rows*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");
}
if (temp_buffer[j*Qm + i*rows*Qm + k]) {
interleaver_buffer[j*Qm + i*rows*Qm + k] = 0;
} else {
q_bits[j*Qm + i*rows*Qm + k] = g_bits[idx];
idx++;
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,
@ -551,15 +588,13 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
uint32_t nb_q = cfg->nbits.nof_bits;
uint32_t Qm = cfg->grant.Qm;
bzero(q_bits, sizeof(uint8_t) * nb_q);
// Encode RI
if (uci_data.uci_ri_len > 0) {
float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri];
if (cfg->cb_segm.tbs == 0) {
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) {
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,
uci_data.uci_cqi, uci_data.uci_cqi_len,
beta_cqi_offset[cfg->uci_cfg.I_offset_cqi],
Q_prime_ri, g_bits);
Q_prime_ri, q->temp_g_bits);
if (ret < 0) {
return 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;
// Encode UL-SCH
if (cfg->cb_segm.tbs > 0) {
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,
data, &g_bits[e_offset]);
data, &g_bits[e_offset/8], e_offset%8);
if (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)
q->uci_pos.idx=0;
ulsch_interleave(&q->uci_pos, g_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits);
ulsch_interleave(g_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits, q->ack_ri_bits, Q_prime_ri*Qm,
q->ul_interleaver, q->temp_g_bits, SRSLTE_MAX_PRB*12*12*12);
// Encode (and interleave) ACK
if (uci_data.uci_ack_len > 0) {
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
if (cfg->cb_segm.tbs == 0) {
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) {
return 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);
return SRSLTE_SUCCESS;

@ -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 */
static int uci_ulsch_interleave_ack(srslte_uci_pos_t *q, uint8_t ack_coded_bits[6], uint32_t ack_q_bit_idx,
/* Generates UCI-ACK bits and computes position in q bits */
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,
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_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 col = SRSLTE_CP_ISNORM(cp)?ack_column_set_norm[colidx]:ack_column_set_ext[colidx];
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];
// 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");
}
ack_bits[k].position = row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k;
ack_bits[k].type = ack_coded_bits[k];
}
return SRSLTE_SUCCESS;
} 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 */
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,
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_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];
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;
} else {
@ -323,21 +318,20 @@ static uint32_t Q_prime_ri_ack(srslte_pusch_cfg_t *cfg,
return Q_prime;
}
static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Qm) {
q_encoded_bits[0] = data;
q_encoded_bits[1] = SRSLTE_UCI_ACK_RI_PLACEHOLDER_REPETITION;
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?UCI_BIT_1:UCI_BIT_0;
q_encoded_bits[1] = UCI_BIT_REPETITION;
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
* Currently only supporting 1-bit HARQ
*/
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, srslte_uci_pos_t *pos,
uint8_t data,
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t data,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits)
srslte_uci_bit_t *ack_bits)
{
if (beta < 0) {
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);
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);
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;
@ -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,
uint8_t data,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits)
srslte_uci_bit_t *ri_bits)
{
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
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);
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;

@ -167,7 +167,7 @@ int main(int argc, char **argv) {
srslte_uci_data_t uci_data;
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_ack_len = 0;
@ -202,7 +202,7 @@ int main(int argc, char **argv) {
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");
goto quit;
}

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

@ -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) {
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) {
void scrambling_b(uint8_t *c, uint8_t *data, int offset, int len) {
int i;
assert (len + offset <= s->len);
// Do XOR on a word basis
if (!(len%8)) {
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++) {
x[i] = (x[i] ^ y[i]);
}
} else if (!(len%4)) {
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++) {
x[i] = (x[i] ^ y[i]);
}
} else if (!(len%2)) {
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++) {
x[i] = (x[i] ^ y[i]);
}
} else {
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);
}

@ -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)
{
static const uint8_t mask_src[] =
{ 0x00, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
static const uint8_t mask_dst[] =
{ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
if ((dst_offset%8) == (src_offset%8)) {
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);
}
if ((dst_offset%8) == 0 && (src_offset%8) == 0) {
// copy rest of words
memcpy(&dst[dst_offset/8], &src[src_offset/8], nof_bits/8);
// copy last word
if ((src_offset%8+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];
if (nof_bits%8) {
dst[dst_offset/8+nof_bits/8] = src[src_offset/8+nof_bits/8] & mask_dst[nof_bits%8];
}
} else {
bitarray_copy(src, src_offset, nof_bits, dst, dst_offset);

Loading…
Cancel
Save