diff --git a/matlab/tests/pdsch_decode_signal.m b/matlab/tests/pdsch_decode_signal.m index 6208a5210..d376c5c3f 100644 --- a/matlab/tests/pdsch_decode_signal.m +++ b/matlab/tests/pdsch_decode_signal.m @@ -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'); diff --git a/srslte/examples/pdsch_enodeb.c b/srslte/examples/pdsch_enodeb.c index 1d0e28cfe..fdacde801 100644 --- a/srslte/examples/pdsch_enodeb.c +++ b/srslte/examples/pdsch_enodeb.c @@ -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); diff --git a/srslte/include/srslte/phch/dci.h b/srslte/include/srslte/phch/dci.h index 3edbac392..c3fe268e1 100644 --- a/srslte/include/srslte/phch/dci.h +++ b/srslte/include/srslte/phch/dci.h @@ -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); diff --git a/srslte/include/srslte/phch/pdcch.h b/srslte/include/srslte/phch/pdcch.h index 10b6f9fa5..b0f09a898 100644 --- a/srslte/include/srslte/phch/pdcch.h +++ b/srslte/include/srslte/phch/pdcch.h @@ -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, diff --git a/srslte/include/srslte/phch/ra.h b/srslte/include/srslte/phch/ra.h index 9edbfce3c..0b51331f3 100644 --- a/srslte/include/srslte/phch/ra.h +++ b/srslte/include/srslte/phch/ra.h @@ -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, diff --git a/srslte/include/srslte/ue/ue_dl.h b/srslte/include/srslte/ue/ue_dl.h index 3711f9f32..07bcd9470 100644 --- a/srslte/include/srslte/ue/ue_dl.h +++ b/srslte/include/srslte/ue/ue_dl.h @@ -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 diff --git a/srslte/include/srslte/utils/vector.h b/srslte/include/srslte/utils/vector.h index 897adf789..027487818 100644 --- a/srslte/include/srslte/utils/vector.h +++ b/srslte/include/srslte/utils/vector.h @@ -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); diff --git a/srslte/lib/enb/enb_dl.c b/srslte/lib/enb/enb_dl.c index db4fbdd9d..958133ea5 100644 --- a/srslte/lib/enb/enb_dl.c +++ b/srslte/lib/enb/enb_dl.c @@ -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; diff --git a/srslte/lib/phch/dci.c b/srslte/lib/phch/dci.c index 69fedaead..57dc9862a 100644 --- a/srslte/lib/phch/dci.c +++ b/srslte/lib/phch/dci.c @@ -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) { diff --git a/srslte/lib/phch/pdcch.c b/srslte/lib/phch/pdcch.c index a63cc7489..8a67f8d0f 100644 --- a/srslte/lib/phch/pdcch.c +++ b/srslte/lib/phch/pdcch.c @@ -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++) { diff --git a/srslte/lib/phch/ra.c b/srslte/lib/phch/ra.c index eaad6c5eb..f005cd9aa 100644 --- a/srslte/lib/phch/ra.c +++ b/srslte/lib/phch/ra.c @@ -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; } diff --git a/srslte/lib/phch/test/dci_unpacking.c b/srslte/lib/phch/test/dci_unpacking.c index aca2e3777..7e65b433f 100644 --- a/srslte/lib/phch/test/dci_unpacking.c +++ b/srslte/lib/phch/test/dci_unpacking.c @@ -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: diff --git a/srslte/lib/phch/test/pdcch_file_test.c b/srslte/lib/phch/test/pdcch_file_test.c index 4f9f99cbe..9f6af1afd 100644 --- a/srslte/lib/phch/test/pdcch_file_test.c +++ b/srslte/lib/phch/test/pdcch_file_test.c @@ -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); diff --git a/srslte/lib/phch/test/pdcch_test.c b/srslte/lib/phch/test/pdcch_test.c index 520e2251e..d03532b45 100644 --- a/srslte/lib/phch/test/pdcch_test.c +++ b/srslte/lib/phch/test/pdcch_test.c @@ -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;isample_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); } diff --git a/srslte/lib/utils/vector.c b/srslte/lib/utils/vector.c index e88d0890f..1cd91c7a5 100644 --- a/srslte/lib/utils/vector.c +++ b/srslte/lib/utils/vector.c @@ -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