Added unpacking for MIMO

master
Ismael Gomez 8 years ago
parent 15735c35c7
commit 299dc6aef4

@ -1,6 +1,6 @@
enb=struct('NCellID',1,'NDLRB',25,'NSubframe',5,'CFI',2,'CyclicPrefix','Normal','CellRefP',1,'Ng','Sixth','PHICHDuration','Normal','DuplexMode','FDD');
enb=struct('NCellID',137,'NDLRB',50,'NSubframe',8,'CFI',1,'CyclicPrefix','Normal','CellRefP',2,'Ng','One','PHICHDuration','Normal','DuplexMode','FDD');
RNTI=65535;
RNTI=5;
addpath('../../build/srslte/lib/phch/test')
@ -29,7 +29,7 @@ if ~isempty(dci)
% Get the PDSCH configuration from the DCI
[pdsch, trblklen] = hPDSCHConfiguration(enb, dci, pdcch.RNTI);
pdsch.NTurboDecIts = 10;
pdsch.NTurboDecIts = 16;
%pdsch.Modulation = {'64QAM'};
pdsch.RV=0;
fprintf('PDSCH settings after DCI decoding:\n');
@ -46,17 +46,23 @@ if ~isempty(dci)
[dec2, data, pdschRx2, pdschSymbols2, e_bits] = srslte_pdsch(enb, pdsch, ...
trblklen, ...
subframe_rx, hest, 0);
subframe_rx);
scatter(real(pdschSymbols{1}),imag(pdschSymbols{1}))
if crc == 0
fprintf('PDSCH OK.\n\n');
fprintf('PDSCH Matlab OK.\n\n');
else
fprintf('PDSCH ERROR.\n\n');
fprintf('PDSCH Matlab ERROR.\n\n');
end
if dec2 == 1
fprintf('PDSCH srsLTE OK.\n\n');
else
fprintf('PDSCH srsLTE ERROR.\n\n');
end
else
% indicate that DCI decoding failed
fprintf('DCI decoding failed.\n\n');

@ -609,7 +609,7 @@ int main(int argc, char **argv) {
/* Encode PDCCH */
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
srslte_dci_msg_pack_pdsch(&ra_dl, &dci_msg, SRSLTE_DCI_FORMAT1, cell.nof_prb, false);
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_msg, cell.nof_prb, false);
if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], UE_CRNTI, sf_symbols, sf_idx, cfi)) {
fprintf(stderr, "Error encoding DCI message\n");
exit(-1);

@ -52,7 +52,14 @@ typedef enum {
SRSLTE_DCI_FORMAT1,
SRSLTE_DCI_FORMAT1A,
SRSLTE_DCI_FORMAT1C,
SRSLTE_DCI_FORMAT_ERROR
SRSLTE_DCI_FORMAT1B,
SRSLTE_DCI_FORMAT1D,
SRSLTE_DCI_FORMAT2,
SRSLTE_DCI_FORMAT2A,
SRSLTE_DCI_FORMAT2B,
//SRSLTE_DCI_FORMAT3,
//SRSLTE_DCI_FORMAT3A,
SRSLTE_DCI_NOF_FORMATS
} srslte_dci_format_t;
// Each type is for a different interface to packing/unpacking functions
@ -80,6 +87,7 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API {
uint8_t data[SRSLTE_DCI_MAX_BITS];
uint32_t nof_bits;
srslte_dci_format_t format;
} srslte_dci_msg_t;
typedef struct SRSLTE_API {
@ -97,6 +105,7 @@ typedef struct SRSLTE_API {
SRSLTE_API int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg,
uint16_t msg_rnti,
uint32_t nof_prb,
uint32_t nof_ports,
srslte_ra_dl_dci_t *dl_dci,
srslte_ra_dl_grant_t *grant);
@ -151,19 +160,22 @@ SRSLTE_API int srslte_dci_msg_unpack_pusch(srslte_dci_msg_t *msg,
// For srslte_dci_msg_type_t = SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED
SRSLTE_API int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data,
srslte_dci_format_t format,
srslte_dci_msg_t *msg,
srslte_dci_format_t format,
uint32_t nof_prb,
bool crc_is_crnti);
SRSLTE_API int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg,
srslte_ra_dl_dci_t *data,
uint32_t nof_prb,
uint32_t nof_ports,
bool crc_is_crnti);
SRSLTE_API uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format,
uint32_t nof_prb);
uint32_t nof_prb,
uint32_t nof_ports);
// This is for backwards compatibility only for tm1 formats
SRSLTE_API uint32_t srslte_dci_format_sizeof_lut(srslte_dci_format_t format,
uint32_t nof_prb);

@ -114,6 +114,26 @@ SRSLTE_API int srslte_pdcch_decode_msg(srslte_pdcch_t *q,
srslte_dci_format_t format,
uint16_t *crc_rem);
SRSLTE_API int srslte_pdcch_dci_decode(srslte_pdcch_t *q,
float *e,
uint8_t *data,
uint32_t E,
uint32_t nof_bits,
uint16_t *crc);
SRSLTE_API int srslte_pdcch_dci_encode(srslte_pdcch_t *q,
uint8_t *data,
uint8_t *e,
uint32_t nof_bits,
uint32_t E,
uint16_t rnti);
SRSLTE_API void srslte_pdcch_dci_encode_conv(srslte_pdcch_t *q,
uint8_t *data,
uint32_t nof_bits,
uint8_t *coded_data,
uint16_t rnti);
/* Function for generation of UE-specific search space DCI locations */
SRSLTE_API uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q,
srslte_dci_location_t *locations,

@ -109,12 +109,6 @@ typedef struct SRSLTE_API {
/** Unpacked DCI message for DL grant */
typedef struct SRSLTE_API {
enum {
SRSLTE_RA_DCI_FORMAT1,
SRSLTE_RA_DCI_FORMAT1A,
SRSLTE_RA_DCI_FORMAT1C,
} dci_format;
srslte_ra_type_t alloc_type;
union {
srslte_ra_type0_t type0_alloc;
@ -122,10 +116,22 @@ typedef struct SRSLTE_API {
srslte_ra_type2_t type2_alloc;
};
uint32_t mcs_idx;
uint32_t harq_process;
uint32_t mcs_idx;
int rv_idx;
bool ndi;
bool ndi;
uint32_t mcs_idx_1;
int rv_idx_1;
bool ndi_1;
bool tb_cw_swap;
bool sram_id;
uint8_t pinfo;
bool pconf;
bool power_offset;
bool dci_is_1a;
bool dci_is_1c;
} srslte_ra_dl_dci_t;
@ -185,8 +191,6 @@ typedef union {
* Functions
**************************************************/
SRSLTE_API char* srslte_ra_dl_dci_string(srslte_ra_dl_dci_t *dci);
SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
uint32_t nof_prb,
uint16_t rnti,

@ -171,7 +171,8 @@ SRSLTE_API void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q,
SRSLTE_API void srslte_ue_dl_save_signal(srslte_ue_dl_t *q,
srslte_softbuffer_rx_t *softbuffer,
uint32_t tti,
uint32_t rv_idx);
uint32_t rv_idx,
uint16_t rnti);
#endif

@ -70,6 +70,7 @@ SRSLTE_API void srslte_vec_fprint_byte(FILE *stream, uint8_t *x, uint32_t len);
SRSLTE_API void srslte_vec_fprint_i(FILE *stream, int *x, uint32_t len);
SRSLTE_API void srslte_vec_fprint_s(FILE *stream, short *x, uint32_t len);
SRSLTE_API void srslte_vec_fprint_hex(FILE *stream, uint8_t *x, uint32_t len);
SRSLTE_API void srslte_vec_sprint_hex(char *str, uint8_t *x, uint32_t len);
/* Saves/loads a vector to a file */
SRSLTE_API void srslte_vec_save_file(char *filename, void *buffer, uint32_t len);

@ -239,7 +239,8 @@ int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant,
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || (rnti >= SRSLTE_RARNTI_START && rnti <= SRSLTE_RARNTI_END)) {
rnti_is_user = false;
}
srslte_dci_msg_pack_pdsch(grant, &dci_msg, format, q->cell.nof_prb, rnti_is_user);
srslte_dci_msg_pack_pdsch(grant, format, &dci_msg, q->cell.nof_prb, rnti_is_user);
if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) {
fprintf(stderr, "Error encoding DCI message\n");
return SRSLTE_ERROR;

@ -44,7 +44,7 @@
/* Unpacks a DCI message and configures the DL grant object
*/
int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg, uint16_t msg_rnti,
uint32_t nof_prb,
uint32_t nof_prb, uint32_t nof_ports,
srslte_ra_dl_dci_t *dl_dci,
srslte_ra_dl_grant_t *grant)
{
@ -55,44 +55,28 @@ int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg, uint16_t msg_rnti,
{
ret = SRSLTE_ERROR;
srslte_dci_msg_type_t type;
bzero(dl_dci, sizeof(srslte_ra_dl_dci_t));
bzero(grant, sizeof(srslte_ra_dl_grant_t));
if (srslte_dci_msg_get_type(msg, &type, nof_prb, msg_rnti)) {
fprintf(stderr, "Can't get DCI message type\n");
return ret;
bool crc_is_crnti = false;
if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) {
crc_is_crnti = true;
}
srslte_dci_format_t tmp = msg->format;
ret = srslte_dci_msg_unpack_pdsch(msg, dl_dci, nof_prb, nof_ports, crc_is_crnti);
if (ret) {
fprintf(stderr, "Can't unpack DCI message %s (%d)\n", srslte_dci_format_string(tmp), ret);
return ret;
}
srslte_ra_dl_dci_to_grant(dl_dci, nof_prb, msg_rnti, grant);
if (SRSLTE_VERBOSE_ISINFO()) {
INFO("",0);
srslte_dci_msg_type_fprint(stdout, type);
srslte_ra_pdsch_fprint(stdout, dl_dci, nof_prb);
srslte_ra_dl_grant_fprint(stdout, grant);
}
if (type.type == SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED) {
bzero(dl_dci, sizeof(srslte_ra_dl_dci_t));
bzero(grant, sizeof(srslte_ra_dl_grant_t));
bool crc_is_crnti = false;
if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) {
crc_is_crnti = true;
}
if (srslte_dci_msg_unpack_pdsch(msg, dl_dci, nof_prb, crc_is_crnti)) {
fprintf(stderr, "Can't unpack DCI message\n");
return ret;
}
srslte_ra_dl_dci_to_grant(dl_dci, nof_prb, msg_rnti, grant);
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pdsch_fprint(stdout, dl_dci, nof_prb);
srslte_ra_dl_grant_fprint(stdout, grant);
}
ret = SRSLTE_SUCCESS;
} else {
if (SRSLTE_VERBOSE_ISINFO()) {
fprintf(stderr, "Unsupported message type: ");
srslte_dci_msg_type_fprint(stderr, type);
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
@ -298,7 +282,84 @@ uint32_t dci_format1C_sizeof(uint32_t nof_prb) {
return n;
}
uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format, uint32_t nof_prb) {
// Number of TPMI bits
uint32_t tpmi_bits(uint32_t nof_ports) {
if (nof_ports <= 2) {
return 2;
} else {
return 4;
}
}
uint32_t dci_format1B_sizeof(uint32_t nof_prb, uint32_t nof_ports) {
// same as format1A minus the differentiation bit plus TPMI + PMI
uint32_t n = dci_format1A_sizeof(nof_prb)-1+tpmi_bits(nof_ports)+1;
while (is_ambiguous_size(n)) {
n++;
}
return n;
}
uint32_t dci_format1D_sizeof(uint32_t nof_prb, uint32_t nof_ports) {
// same size as format1B
return dci_format1B_sizeof(nof_prb, nof_ports);
}
// Number of bits for precoding information
uint32_t precoding_bits_f2(uint32_t nof_ports) {
if (nof_ports <= 2) {
return 3;
} else {
return 6;
}
}
uint32_t dci_format2_sizeof(uint32_t nof_prb, uint32_t nof_ports) {
uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+3+1+2*(5+1+2)+precoding_bits_f2(nof_ports);
if (nof_prb > 10) {
n++;
}
while (is_ambiguous_size(n)) {
n++;
}
return n;
}
// Number of bits for precoding information
uint32_t precoding_bits_f2a(uint32_t nof_ports) {
if (nof_ports <= 2) {
return 0;
} else {
return 2;
}
}
uint32_t dci_format2A_sizeof(uint32_t nof_prb, uint32_t nof_ports) {
uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+3+1+2*(5+1+2)+precoding_bits_f2a(nof_ports);
if (nof_prb > 10) {
n++;
}
while (is_ambiguous_size(n)) {
n++;
}
return n;
}
uint32_t dci_format2B_sizeof(uint32_t nof_prb, uint32_t nof_ports) {
uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+3+1+2*(5+1+2);
if (nof_prb > 10) {
n++;
}
while (is_ambiguous_size(n)) {
n++;
}
return n;
}
uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format, uint32_t nof_prb, uint32_t nof_ports) {
switch (format) {
case SRSLTE_DCI_FORMAT0:
return dci_format0_sizeof(nof_prb);
@ -308,13 +369,29 @@ uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format, uint32_t nof_prb)
return dci_format1A_sizeof(nof_prb);
case SRSLTE_DCI_FORMAT1C:
return dci_format1C_sizeof(nof_prb);
case SRSLTE_DCI_FORMAT1B:
return dci_format1B_sizeof(nof_prb, nof_ports);
case SRSLTE_DCI_FORMAT1D:
return dci_format1D_sizeof(nof_prb, nof_ports);
case SRSLTE_DCI_FORMAT2:
return dci_format2_sizeof(nof_prb, nof_ports);
case SRSLTE_DCI_FORMAT2A:
return dci_format2A_sizeof(nof_prb, nof_ports);
case SRSLTE_DCI_FORMAT2B:
return dci_format2B_sizeof(nof_prb, nof_ports);
/*
case SRSLTE_DCI_FORMAT3:
return dci_format3_sizeof(nof_prb);
case SRSLTE_DCI_FORMAT3A:
return dci_format3A_sizeof(nof_prb);
*/
default:
return SRSLTE_ERROR;
}
}
uint32_t srslte_dci_format_sizeof_lut(srslte_dci_format_t format, uint32_t nof_prb) {
if (nof_prb <= 100 && format < 4) {
if (nof_prb <= 100 && format < 11) {
return dci_sz_table[nof_prb][format];
} else {
return 0;
@ -549,8 +626,6 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t
// TPC not implemented
data->dci_format = SRSLTE_RA_DCI_FORMAT1;
return SRSLTE_SUCCESS;
}
@ -666,6 +741,8 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32
return SRSLTE_ERROR;
}
data->dci_is_1a = true;
// Check if RA procedure by PDCCH order
if (*y == 0) {
int nof_bits = riv_nbits(nof_prb);
@ -735,7 +812,50 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32
data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS
}
data->dci_format = SRSLTE_RA_DCI_FORMAT1A;
return SRSLTE_SUCCESS;
}
int dci_format1B_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb, uint32_t nof_ports)
{
/* pack bits */
uint8_t *y = msg->data;
data->alloc_type = SRSLTE_RA_ALLOC_TYPE2;
data->type2_alloc.mode = *y++;
// by default, set N_gap to 1
data->type2_alloc.n_gap = SRSLTE_RA_TYPE2_NG1;
/* unpack RIV according to 7.1.6.3 of 36.213 */
uint32_t nb_gap = 0;
if (data->type2_alloc.mode == SRSLTE_RA_TYPE2_DIST && nof_prb >= 50) {
nb_gap = 1;
data->type2_alloc.n_gap = *y++;
}
uint32_t nof_vrb;
if (data->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
nof_vrb = nof_prb;
} else {
nof_vrb = srslte_ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1);
}
uint32_t riv = srslte_bit_pack(&y, riv_nbits(nof_prb) - nb_gap);
srslte_ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start,
nof_prb, nof_vrb);
data->type2_alloc.riv = riv;
// unpack MCS, Harq pid and ndi
data->mcs_idx = srslte_bit_pack(&y, 5);
data->harq_process = srslte_bit_pack(&y, 3);
data->ndi = *y++ ? true : false;
data->rv_idx = srslte_bit_pack(&y, 2);
// Ignore TPC command for PUCCH
y += 2;
data->pinfo = srslte_bit_pack(&y, tpmi_bits(nof_ports));
data->pconf = *y++ ? true : false;
return SRSLTE_SUCCESS;
}
@ -803,6 +923,9 @@ int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32
fprintf(stderr, "Invalid message length for format 1C\n");
return SRSLTE_ERROR;
}
data->dci_is_1c = true;
data->alloc_type = SRSLTE_RA_ALLOC_TYPE2;
data->type2_alloc.mode = SRSLTE_RA_TYPE2_DIST;
if (nof_prb >= 50) {
@ -821,7 +944,6 @@ int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32
data->mcs_idx = srslte_bit_pack(&y, 5);
data->dci_format = SRSLTE_RA_DCI_FORMAT1C;
data->rv_idx = -1; // For SI-RNTI, get RV from TTI
msg->nof_bits = (y - msg->data);
@ -829,8 +951,124 @@ int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32
return SRSLTE_SUCCESS;
}
int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, srslte_dci_format_t format,
uint32_t nof_prb, bool crc_is_crnti) {
int dci_format1D_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb, uint32_t nof_ports)
{
/* pack bits */
uint8_t *y = msg->data;
data->alloc_type = SRSLTE_RA_ALLOC_TYPE2;
data->type2_alloc.mode = *y++;
// by default, set N_gap to 1
data->type2_alloc.n_gap = SRSLTE_RA_TYPE2_NG1;
/* unpack RIV according to 7.1.6.3 of 36.213 */
uint32_t nb_gap = 0;
if (data->type2_alloc.mode == SRSLTE_RA_TYPE2_DIST && nof_prb >= 50) {
nb_gap = 1;
data->type2_alloc.n_gap = *y++;
}
uint32_t nof_vrb;
if (data->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) {
nof_vrb = nof_prb;
} else {
nof_vrb = srslte_ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == SRSLTE_RA_TYPE2_NG1);
}
uint32_t riv = srslte_bit_pack(&y, riv_nbits(nof_prb) - nb_gap);
srslte_ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start,
nof_prb, nof_vrb);
data->type2_alloc.riv = riv;
// unpack MCS, Harq pid and ndi
data->mcs_idx = srslte_bit_pack(&y, 5);
data->harq_process = srslte_bit_pack(&y, 3);
data->ndi = *y++ ? true : false;
data->rv_idx = srslte_bit_pack(&y, 2);
// Ignore TPC command for PUCCH
y += 2;
data->pinfo = srslte_bit_pack(&y, tpmi_bits(nof_ports));
data->power_offset = *y++ ? true : false;
return SRSLTE_SUCCESS;
}
int dci_format2AB_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb, uint32_t nof_ports) {
/* pack bits */
uint8_t *y = msg->data;
if (nof_prb > 10) {
data->alloc_type = *y++;
} else {
data->alloc_type = SRSLTE_RA_ALLOC_TYPE0;
}
/* Resource allocation: type0 or type 1 */
uint32_t P = srslte_ra_type0_P(nof_prb);
uint32_t alloc_size = (uint32_t) ceilf((float) nof_prb / P);
switch (data->alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
data->type0_alloc.rbg_bitmask = srslte_bit_pack(&y, alloc_size);
break;
case SRSLTE_RA_ALLOC_TYPE1:
data->type1_alloc.rbg_subset = srslte_bit_pack(&y, (int) ceilf(log2f(P)));
data->type1_alloc.shift = *y++ ? true : false;
data->type1_alloc.vrb_bitmask = srslte_bit_pack(&y,
alloc_size - (int) ceilf(log2f(P)) - 1);
break;
default:
fprintf(stderr, "Format2 accepts type0 or type1 resource allocation only\n");
return SRSLTE_ERROR;
}
// unpack TPC command for PUCCH (not implemented)
y+=2;
/* harq process number */
data->harq_process = srslte_bit_pack(&y, 3);
// Transpor block to codeword swap flag
if (msg->format == SRSLTE_DCI_FORMAT2B) {
data->sram_id = *y++ ? true : false;
} else {
data->tb_cw_swap = *y++ ? true : false;
}
/* unpack MCS according to 7.1.7 of 36.213 */
data->mcs_idx = srslte_bit_pack(&y, 5);
data->ndi = *y++ ? true : false;
// rv version
data->rv_idx = srslte_bit_pack(&y, 2);
// same for tb1
data->mcs_idx_1 = srslte_bit_pack(&y, 5);
data->ndi_1 = *y++ ? true : false;
data->rv_idx_1 = srslte_bit_pack(&y, 2);
// Precoding information
if (msg->format == SRSLTE_DCI_FORMAT2A) {
data->pinfo = srslte_bit_pack(&y, precoding_bits_f2(nof_ports));
} else if (msg->format == SRSLTE_DCI_FORMAT2A) {
data->pinfo = srslte_bit_pack(&y, precoding_bits_f2a(nof_ports));
}
return SRSLTE_SUCCESS;
}
int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data, srslte_dci_format_t format,
srslte_dci_msg_t *msg, uint32_t nof_prb,
bool crc_is_crnti)
{
msg->format = format;
switch (format) {
case SRSLTE_DCI_FORMAT1:
return dci_format1_pack(data, msg, nof_prb);
@ -839,23 +1077,36 @@ int srslte_dci_msg_pack_pdsch(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, s
case SRSLTE_DCI_FORMAT1C:
return dci_format1Cs_pack(data, msg, nof_prb);
default:
fprintf(stderr, "Invalid DCI format %s for PDSCH resource allocation\n",
fprintf(stderr, "DCI pack pdsch: Invalid DCI format %s in \n",
srslte_dci_format_string(format));
return SRSLTE_ERROR;
}
}
int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t nof_prb,
bool crc_is_crnti) {
if (msg->nof_bits == srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1, nof_prb)) {
return dci_format1_unpack(msg, data, nof_prb);
} else if (msg->nof_bits == srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1A, nof_prb)) {
return dci_format1As_unpack(msg, data, nof_prb, crc_is_crnti);
} else if (msg->nof_bits == srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1C, nof_prb)) {
return dci_format1Cs_unpack(msg, data, nof_prb);
} else {
return SRSLTE_ERROR;
}
int srslte_dci_msg_unpack_pdsch(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data,
uint32_t nof_prb, uint32_t nof_ports, bool crc_is_crnti)
{
switch (msg->format) {
case SRSLTE_DCI_FORMAT1:
return dci_format1_unpack(msg, data, nof_prb);
case SRSLTE_DCI_FORMAT1A:
return dci_format1As_unpack(msg, data, nof_prb, crc_is_crnti);
case SRSLTE_DCI_FORMAT1B:
return dci_format1B_unpack(msg, data, nof_prb, nof_ports);
case SRSLTE_DCI_FORMAT1C:
return dci_format1Cs_unpack(msg, data, nof_prb);
case SRSLTE_DCI_FORMAT1D:
return dci_format1D_unpack(msg, data, nof_prb, nof_ports);
case SRSLTE_DCI_FORMAT2:
case SRSLTE_DCI_FORMAT2A:
case SRSLTE_DCI_FORMAT2B:
return dci_format2AB_unpack(msg, data, nof_prb, nof_ports);
default:
fprintf(stderr, "DCI unpack pdsch: Invalid DCI format %s\n",
srslte_dci_format_string(msg->format));
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_dci_msg_pack_pusch(srslte_ra_ul_dci_t *data, srslte_dci_msg_t *msg, uint32_t nof_prb) {
@ -873,23 +1124,43 @@ srslte_dci_format_t srslte_dci_format_from_string(char *str) {
return SRSLTE_DCI_FORMAT1;
} else if (!strcmp(str, "Format1A")) {
return SRSLTE_DCI_FORMAT1A;
} else if (!strcmp(str, "Format1B")) {
return SRSLTE_DCI_FORMAT1B;
} else if (!strcmp(str, "Format1C")) {
return SRSLTE_DCI_FORMAT1C;
} else if (!strcmp(str, "Format1D")) {
return SRSLTE_DCI_FORMAT1D;
} else if (!strcmp(str, "Format2")) {
return SRSLTE_DCI_FORMAT2;
} else if (!strcmp(str, "Format2A")) {
return SRSLTE_DCI_FORMAT2A;
} else if (!strcmp(str, "Format2B")) {
return SRSLTE_DCI_FORMAT2B;
} else {
return SRSLTE_DCI_FORMAT_ERROR;
return SRSLTE_DCI_NOF_FORMATS;
}
}
char* srslte_dci_format_string(srslte_dci_format_t format) {
switch (format) {
case SRSLTE_DCI_FORMAT0:
return "Format0";
return "Format0 ";
case SRSLTE_DCI_FORMAT1:
return "Format1";
return "Format1 ";
case SRSLTE_DCI_FORMAT1A:
return "Format1A";
case SRSLTE_DCI_FORMAT1B:
return "Format1B";
case SRSLTE_DCI_FORMAT1C:
return "Format1C";
case SRSLTE_DCI_FORMAT1D:
return "Format1D";
case SRSLTE_DCI_FORMAT2:
return "Format2 ";
case SRSLTE_DCI_FORMAT2A:
return "Format2A";
case SRSLTE_DCI_FORMAT2B:
return "Format2B";
default:
return "N/A"; // fatal error
}
@ -916,6 +1187,7 @@ void srslte_dci_msg_type_fprint(FILE *f, srslte_dci_msg_type_t type) {
}
}
/** Warning this function will be deprecated. Currently only used in test programs */
int srslte_dci_msg_get_type(srslte_dci_msg_t *msg, srslte_dci_msg_type_t *type, uint32_t nof_prb,
uint16_t msg_rnti)
{

@ -270,7 +270,7 @@ uint32_t srslte_pdcch_common_locations_ncce(uint32_t nof_cce, srslte_dci_locatio
*
* TODO: UE transmit antenna selection CRC mask
*/
static int dci_decode(srslte_pdcch_t *q, float *e, uint8_t *data, uint32_t E, uint32_t nof_bits, uint16_t *crc) {
int srslte_pdcch_dci_decode(srslte_pdcch_t *q, float *e, uint8_t *data, uint32_t E, uint32_t nof_bits, uint16_t *crc) {
uint16_t p_bits, crc_res;
uint8_t *x;
@ -336,14 +336,20 @@ int srslte_pdcch_decode_msg(srslte_pdcch_t *q,
}
mean /= e_bits;
if (mean > 0.5) {
ret = dci_decode(q, &q->llr[location->ncce * 72],
ret = srslte_pdcch_dci_decode(q, &q->llr[location->ncce * 72],
msg->data, e_bits, nof_bits, crc_rem);
if (ret == SRSLTE_SUCCESS) {
msg->nof_bits = nof_bits;
// Check format differentiation
if (format == SRSLTE_DCI_FORMAT0 || format == SRSLTE_DCI_FORMAT1A) {
msg->format = (msg->data[0] == 0)?SRSLTE_DCI_FORMAT0:SRSLTE_DCI_FORMAT1A;
} else {
msg->format = format;
}
}
if (crc_rem) {
DEBUG("Decoded DCI: nCCE=%d, L=%d, msg_len=%d, mean=%f, crc_rem=0x%x\n",
location->ncce, location->L, nof_bits, mean, *crc_rem);
DEBUG("Decoded DCI: nCCE=%d, L=%d, format=%s, msg_len=%d, mean=%f, crc_rem=0x%x\n",
location->ncce, location->L, srslte_dci_format_string(format), nof_bits, mean, *crc_rem);
}
} else {
DEBUG("Skipping DCI: nCCE=%d, L=%d, msg_len=%d, mean=%f\n",
@ -443,12 +449,26 @@ static void crc_set_mask_rnti(uint8_t *crc, uint16_t rnti) {
}
}
void srslte_pdcch_dci_encode_conv(srslte_pdcch_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *coded_data, uint16_t rnti) {
srslte_convcoder_t encoder;
int poly[3] = { 0x6D, 0x4F, 0x57 };
encoder.K = 7;
encoder.R = 3;
encoder.tail_biting = true;
memcpy(encoder.poly, poly, 3 * sizeof(int));
srslte_crc_attach(&q->crc, data, nof_bits);
crc_set_mask_rnti(&data[nof_bits], rnti);
srslte_convcoder_encode(&encoder, data, coded_data, nof_bits + 16);
}
/** 36.212 5.3.3.2 to 5.3.3.4
* TODO: UE transmit antenna selection CRC mask
*/
static int dci_encode(srslte_pdcch_t *q, uint8_t *data, uint8_t *e, uint32_t nof_bits, uint32_t E,
uint16_t rnti) {
srslte_convcoder_t encoder;
int srslte_pdcch_dci_encode(srslte_pdcch_t *q, uint8_t *data, uint8_t *e, uint32_t nof_bits, uint32_t E,
uint16_t rnti)
{
uint8_t tmp[3 * (SRSLTE_DCI_MAX_BITS + 16)];
if (q != NULL &&
@ -458,16 +478,7 @@ static int dci_encode(srslte_pdcch_t *q, uint8_t *data, uint8_t *e, uint32_t nof
E < q->max_bits)
{
int poly[3] = { 0x6D, 0x4F, 0x57 };
encoder.K = 7;
encoder.R = 3;
encoder.tail_biting = true;
memcpy(encoder.poly, poly, 3 * sizeof(int));
srslte_crc_attach(&q->crc, data, nof_bits);
crc_set_mask_rnti(&data[nof_bits], rnti);
srslte_convcoder_encode(&encoder, data, tmp, nof_bits + 16);
srslte_pdcch_dci_encode_conv(q, data, nof_bits, tmp, rnti);
DEBUG("CConv output: ", 0);
if (SRSLTE_VERBOSE_ISDEBUG()) {
@ -519,7 +530,7 @@ int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_loc
DEBUG("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n",
msg->nof_bits, e_bits, location.ncce, location.L, rnti);
dci_encode(q, msg->data, q->e, msg->nof_bits, e_bits, rnti);
srslte_pdcch_dci_encode(q, msg->data, q->e, msg->nof_bits, e_bits, rnti);
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {

@ -267,19 +267,6 @@ uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t ce
return nof_re;
}
char* srslte_ra_dl_dci_string(srslte_ra_dl_dci_t *dci) {
switch(dci->dci_format) {
case SRSLTE_RA_DCI_FORMAT1:
return "1";
case SRSLTE_RA_DCI_FORMAT1A:
return "1A";
case SRSLTE_RA_DCI_FORMAT1C:
return "1C";
default:
return "";
}
}
/** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */
static int dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, uint32_t nof_prb) {
int i, j;
@ -400,7 +387,7 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
uint32_t i_tbs = 0;
if (!crc_is_crnti) {
if (dci->dci_format == SRSLTE_RA_DCI_FORMAT1A) {
if (dci->dci_is_1a) {
n_prb = dci->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3;
i_tbs = dci->mcs_idx;
tbs = srslte_ra_tbs_from_idx(i_tbs, n_prb);
@ -458,7 +445,8 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl
}
/** Obtains a DL grant from a DCI grant for PDSCH */
int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, uint32_t nof_prb, uint16_t msg_rnti, srslte_ra_dl_grant_t *grant)
int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
uint32_t nof_prb, uint16_t msg_rnti, srslte_ra_dl_grant_t *grant)
{
bool crc_is_crnti = false;
if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) {
@ -474,7 +462,7 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, uint32_t nof_prb, uint16_
// Apply Section 7.1.7.3. If RA-RNTI and Format1C rv_idx=0
if (msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END &&
dci->dci_format == SRSLTE_RA_DCI_FORMAT1C)
dci->dci_is_1c)
{
dci->rv_idx = 0;
}

@ -91,7 +91,7 @@ int main(int argc, char **argv) {
switch (dci_type.type) {
case SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED:
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
srslte_dci_msg_unpack_pdsch(&msg, &ra_dl, nof_prb, false);
srslte_dci_msg_unpack_pdsch(&msg, &ra_dl, nof_prb, 1, false);
srslte_ra_pdsch_fprint(stdout, &ra_dl, nof_prb);
break;
default:

@ -99,7 +99,7 @@ void parse_args(int argc, char **argv) {
break;
case 'o':
dci_format = srslte_dci_format_from_string(argv[optind]);
if (dci_format == SRSLTE_DCI_FORMAT_ERROR) {
if (dci_format == SRSLTE_DCI_NOF_FORMATS) {
fprintf(stderr, "Error unsupported format %s\n", argv[optind]);
exit(-1);
}
@ -264,7 +264,7 @@ int main(int argc, char **argv) {
switch(type.type) {
case SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED:
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
if (srslte_dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb, rnti != SRSLTE_SIRNTI)) {
if (srslte_dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb, cell.nof_ports, rnti != SRSLTE_SIRNTI)) {
fprintf(stderr, "Can't unpack DCI message\n");
} else {
srslte_ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);

@ -96,7 +96,7 @@ int test_dci_payload_size() {
for (i = 0; i < 6; i++) {
int n = prb[i];
for (j = 0; j < 4; j++) {
x[j] = srslte_dci_format_sizeof(formats[j], n);
x[j] = srslte_dci_format_sizeof(formats[j], n, 1);
if (x[j] != dci_sz[i][j]) {
fprintf(stderr, "Invalid DCI payload size for %s\n",
srslte_dci_format_string(formats[j]));
@ -112,7 +112,7 @@ int test_dci_payload_size() {
for (i=0;i<=100;i++) {
printf(" {");
for (int j=0;j<4;j++) {
printf("%d",srslte_dci_format_sizeof(formats[j], i));
printf("%d",srslte_dci_format_sizeof(formats[j], i, 1));
if (j<3) {
printf(", ");
}
@ -191,11 +191,11 @@ int main(int argc, char **argv) {
ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
ra_dl.type0_alloc.rbg_bitmask = 0x5;
srslte_dci_msg_pack_pdsch(&ra_dl, &dci_tx[0], SRSLTE_DCI_FORMAT1, cell.nof_prb, false);
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_tx[0], cell.nof_prb, false);
srslte_dci_location_set(&dci_locations[0], 0, 0);
ra_dl.mcs_idx = 15;
srslte_dci_msg_pack_pdsch(&ra_dl, &dci_tx[1], SRSLTE_DCI_FORMAT1, cell.nof_prb, false);
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_tx[1], cell.nof_prb, false);
srslte_dci_location_set(&dci_locations[1], 0, 1);
for (i=0;i<nof_dcis;i++) {

@ -103,7 +103,7 @@ void parse_args(int argc, char **argv) {
break;
case 'o':
dci_format = srslte_dci_format_from_string(argv[optind]);
if (dci_format == SRSLTE_DCI_FORMAT_ERROR) {
if (dci_format == SRSLTE_DCI_NOF_FORMATS) {
fprintf(stderr, "Error unsupported format %s\n", argv[optind]);
exit(-1);
}

@ -135,7 +135,6 @@ int main(int argc, char **argv) {
srslte_ra_dl_dci_t dci;
bzero(&dci, sizeof(srslte_ra_dl_dci_t));
dci.dci_format = SRSLTE_DCI_FORMAT1;
dci.mcs_idx = mcs;
dci.rv_idx = rv_idx;
dci.type0_alloc.rbg_bitmask = 0xffffffff;

@ -201,7 +201,6 @@ int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf
q->sample_offset / q->fft.symbol_sz);
}
}
return srslte_ue_dl_decode_estimate(q, sf_idx, cfi);
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
@ -303,7 +302,8 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3
fprintf(stderr, "Error decoding DCI msg\n");
return SRSLTE_ERROR;
}
if (dci_msg->data[0] != 0) {
// Check format differentiation
if (dci_msg->format != SRSLTE_DCI_FORMAT0) {
crc_rem = 0;
}
DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem);
@ -373,7 +373,7 @@ int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg,
INFO("Found DCI nCCE: %d, L: %d, n_bits=%d\n", locations[i].ncce, locations[i].L, srslte_dci_format_sizeof_lut(formats[f], q->cell.nof_prb));
memcpy(&q->last_location, &locations[i], sizeof(srslte_dci_location_t));
}
if (crc_rem == rnti && formats[f] == SRSLTE_DCI_FORMAT1A && dci_msg->data[0] != 1) {
if (crc_rem == rnti && dci_msg->format == SRSLTE_DCI_FORMAT0) {
/* Save Format 0 msg. Recovered next call to srslte_ue_dl_find_ul_dci() */
q->pending_ul_dci_rnti = crc_rem;
memcpy(&q->pending_ul_dci_msg, dci_msg, sizeof(srslte_dci_msg_t));
@ -410,7 +410,7 @@ int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, u
int found_dci = srslte_ue_dl_find_dl_dci(q, &dci_msg, q->cfi, sf_idx, rnti);
if (found_dci == 1) {
if (srslte_dci_msg_to_dl_grant(&dci_msg, rnti, q->cell.nof_prb, &dci_unpacked, &grant)) {
if (srslte_dci_msg_to_dl_grant(&dci_msg, rnti, q->cell.nof_prb, q->cell.nof_ports, &dci_unpacked, &grant)) {
fprintf(stderr, "Error unpacking DCI\n");
return SRSLTE_ERROR;
}
@ -447,7 +447,7 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr
}
}
void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx) {
void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx, uint16_t rnti) {
srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
printf("%d samples\n", SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
srslte_vec_save_file("ce0", q->ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
@ -476,7 +476,7 @@ void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuf
srslte_vec_save_file(tmpstr, softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t));
}
printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, rv=%d, rnti=%d\n", tti, tti%10, q->cfi,
q->pdsch_cfg.grant.mcs.idx, rv_idx, q->current_rnti);
q->pdsch_cfg.grant.mcs.idx, rv_idx, rnti);
}

@ -429,6 +429,23 @@ void srslte_vec_fprint_hex(FILE *stream, uint8_t *x, uint32_t len) {
fprintf(stream, "];\n");
}
void srslte_vec_sprint_hex(char *str, uint8_t *x, uint32_t len) {
uint32_t i, nbytes;
uint8_t byte;
nbytes = len/8;
int n=0;
n+=sprintf(&str[n], "[");
for (i=0;i<nbytes;i++) {
byte = (uint8_t) srslte_bit_pack(&x, 8);
n+=sprintf(&str[n], "%02x ", byte);
}
if (len%8) {
byte = (uint8_t) srslte_bit_pack(&x, len%8)<<(8-(len%8));
n+=sprintf(&str[n], "%02x ", byte);
}
n+=sprintf(&str[n], "];\n");
}
void srslte_vec_save_file(char *filename, void *buffer, uint32_t len) {
FILE *f;
f = fopen(filename, "w");

Loading…
Cancel
Save