|
|
@ -40,7 +40,7 @@
|
|
|
|
#include "liblte/phy/utils/vector.h"
|
|
|
|
#include "liblte/phy/utils/vector.h"
|
|
|
|
#include "liblte/phy/utils/debug.h"
|
|
|
|
#include "liblte/phy/utils/debug.h"
|
|
|
|
|
|
|
|
|
|
|
|
int dci_init(dci_t *q, uint8_t max_dcis) {
|
|
|
|
int dci_init(dci_t *q, uint32_t max_dcis) {
|
|
|
|
q->msg = calloc(sizeof(dci_msg_t), max_dcis);
|
|
|
|
q->msg = calloc(sizeof(dci_msg_t), max_dcis);
|
|
|
|
if (!q->msg) {
|
|
|
|
if (!q->msg) {
|
|
|
|
perror("malloc");
|
|
|
|
perror("malloc");
|
|
|
@ -62,7 +62,7 @@ void dci_candidate_fprint(FILE *f, dci_candidate_t *q) {
|
|
|
|
q->nof_bits);
|
|
|
|
q->nof_bits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int dci_msg_candidate_set(dci_msg_t *msg, uint8_t L, uint8_t nCCE, uint16_t rnti) {
|
|
|
|
int dci_msg_candidate_set(dci_msg_t *msg, uint32_t L, uint32_t nCCE, uint16_t rnti) {
|
|
|
|
if (L >= 0 && L <= 3) {
|
|
|
|
if (L >= 0 && L <= 3) {
|
|
|
|
msg->location.L = L;
|
|
|
|
msg->location.L = L;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -79,13 +79,13 @@ int dci_msg_candidate_set(dci_msg_t *msg, uint8_t L, uint8_t nCCE, uint16_t rnti
|
|
|
|
return LIBLTE_SUCCESS;
|
|
|
|
return LIBLTE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t riv_nbits(uint8_t nof_prb) {
|
|
|
|
uint32_t riv_nbits(uint32_t nof_prb) {
|
|
|
|
return (uint8_t) ceilf(log2f((float) nof_prb * ((float) nof_prb + 1) / 2));
|
|
|
|
return (uint32_t) ceilf(log2f((float) nof_prb * ((float) nof_prb + 1) / 2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const uint8_t ambiguous_sizes[10] = { 12, 14, 16, 20, 24, 26, 32, 40, 44, 56 };
|
|
|
|
const uint32_t ambiguous_sizes[10] = { 12, 14, 16, 20, 24, 26, 32, 40, 44, 56 };
|
|
|
|
|
|
|
|
|
|
|
|
bool is_ambiguous_size(uint8_t size) {
|
|
|
|
bool is_ambiguous_size(uint32_t size) {
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
if (size == ambiguous_sizes[i]) {
|
|
|
|
if (size == ambiguous_sizes[i]) {
|
|
|
@ -98,12 +98,12 @@ bool is_ambiguous_size(uint8_t size) {
|
|
|
|
/**********************************
|
|
|
|
/**********************************
|
|
|
|
* PAYLOAD sizeof functions
|
|
|
|
* PAYLOAD sizeof functions
|
|
|
|
* ********************************/
|
|
|
|
* ********************************/
|
|
|
|
uint8_t dci_format0_sizeof_(uint8_t nof_prb) {
|
|
|
|
uint32_t dci_format0_sizeof_(uint32_t nof_prb) {
|
|
|
|
return 1 + 1 + riv_nbits(nof_prb) + 5 + 1 + 2 + 3 + 1;
|
|
|
|
return 1 + 1 + riv_nbits(nof_prb) + 5 + 1 + 2 + 3 + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t dci_format1A_sizeof(uint8_t nof_prb) {
|
|
|
|
uint32_t dci_format1A_sizeof(uint32_t nof_prb) {
|
|
|
|
uint8_t n;
|
|
|
|
uint32_t n;
|
|
|
|
n = 1 + 1 + riv_nbits(nof_prb) + 5 + 3 + 1 + 2 + 2;
|
|
|
|
n = 1 + 1 + riv_nbits(nof_prb) + 5 + 3 + 1 + 2 + 2;
|
|
|
|
while (n < dci_format0_sizeof_(nof_prb)) {
|
|
|
|
while (n < dci_format0_sizeof_(nof_prb)) {
|
|
|
|
n++;
|
|
|
|
n++;
|
|
|
@ -114,17 +114,17 @@ uint8_t dci_format1A_sizeof(uint8_t nof_prb) {
|
|
|
|
return n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t dci_format0_sizeof(uint8_t nof_prb) {
|
|
|
|
uint32_t dci_format0_sizeof(uint32_t nof_prb) {
|
|
|
|
uint8_t n = dci_format0_sizeof_(nof_prb);
|
|
|
|
uint32_t n = dci_format0_sizeof_(nof_prb);
|
|
|
|
while (n < dci_format1A_sizeof(nof_prb)) {
|
|
|
|
while (n < dci_format1A_sizeof(nof_prb)) {
|
|
|
|
n++;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t dci_format1_sizeof(uint8_t nof_prb) {
|
|
|
|
uint32_t dci_format1_sizeof(uint32_t nof_prb) {
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t n = (uint8_t) ceilf((float) nof_prb / ra_type0_P(nof_prb)) + 5 + 3 + 1 + 2
|
|
|
|
uint32_t n = (uint32_t) ceilf((float) nof_prb / ra_type0_P(nof_prb)) + 5 + 3 + 1 + 2
|
|
|
|
+ 2;
|
|
|
|
+ 2;
|
|
|
|
if (nof_prb > 10) {
|
|
|
|
if (nof_prb > 10) {
|
|
|
|
n++;
|
|
|
|
n++;
|
|
|
@ -136,17 +136,17 @@ uint8_t dci_format1_sizeof(uint8_t nof_prb) {
|
|
|
|
return n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t dci_format1C_sizeof(uint8_t nof_prb) {
|
|
|
|
uint32_t dci_format1C_sizeof(uint32_t nof_prb) {
|
|
|
|
uint8_t n_vrb_dl_gap1 = ra_type2_n_vrb_dl(nof_prb, true);
|
|
|
|
uint32_t n_vrb_dl_gap1 = ra_type2_n_vrb_dl(nof_prb, true);
|
|
|
|
uint8_t n_step = ra_type2_n_rb_step(nof_prb);
|
|
|
|
uint32_t n_step = ra_type2_n_rb_step(nof_prb);
|
|
|
|
uint8_t n = riv_nbits((uint8_t) n_vrb_dl_gap1 / n_step) + 5;
|
|
|
|
uint32_t n = riv_nbits((uint32_t) n_vrb_dl_gap1 / n_step) + 5;
|
|
|
|
if (nof_prb >= 50) {
|
|
|
|
if (nof_prb >= 50) {
|
|
|
|
n++;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t dci_format_sizeof(dci_format_t format, uint8_t nof_prb) {
|
|
|
|
uint32_t dci_format_sizeof(dci_format_t format, uint32_t nof_prb) {
|
|
|
|
switch (format) {
|
|
|
|
switch (format) {
|
|
|
|
case Format0:
|
|
|
|
case Format0:
|
|
|
|
return dci_format0_sizeof(nof_prb);
|
|
|
|
return dci_format0_sizeof(nof_prb);
|
|
|
@ -170,11 +170,11 @@ uint8_t dci_format_sizeof(dci_format_t format, uint8_t nof_prb) {
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* TODO: TPC and cyclic shift for DM RS not implemented
|
|
|
|
* TODO: TPC and cyclic shift for DM RS not implemented
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
|
|
|
|
|
|
|
|
|
|
|
|
/* pack bits */
|
|
|
|
/* pack bits */
|
|
|
|
char *y = msg->data;
|
|
|
|
char *y = msg->data;
|
|
|
|
uint8_t n_ul_hop;
|
|
|
|
uint32_t n_ul_hop;
|
|
|
|
|
|
|
|
|
|
|
|
*y++ = 0; // format differentiation
|
|
|
|
*y++ = 0; // format differentiation
|
|
|
|
if (data->freq_hop_fl == hop_disabled) { // frequency hopping
|
|
|
|
if (data->freq_hop_fl == hop_disabled) { // frequency hopping
|
|
|
@ -193,7 +193,7 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* pack RIV according to 8.1 of 36.213 */
|
|
|
|
/* pack RIV according to 8.1 of 36.213 */
|
|
|
|
uint16_t riv;
|
|
|
|
uint32_t riv;
|
|
|
|
if (data->type2_alloc.L_crb) {
|
|
|
|
if (data->type2_alloc.L_crb) {
|
|
|
|
riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start,
|
|
|
|
riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start,
|
|
|
|
nof_prb);
|
|
|
|
nof_prb);
|
|
|
@ -203,7 +203,7 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - n_ul_hop);
|
|
|
|
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - n_ul_hop);
|
|
|
|
|
|
|
|
|
|
|
|
/* pack MCS according to 8.6.1 of 36.213 */
|
|
|
|
/* pack MCS according to 8.6.1 of 36.213 */
|
|
|
|
uint8_t mcs;
|
|
|
|
uint32_t mcs;
|
|
|
|
if (data->cqi_request) {
|
|
|
|
if (data->cqi_request) {
|
|
|
|
mcs = 29;
|
|
|
|
mcs = 29;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -241,7 +241,7 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
*y++ = data->cqi_request;
|
|
|
|
*y++ = data->cqi_request;
|
|
|
|
|
|
|
|
|
|
|
|
// Padding with zeros
|
|
|
|
// Padding with zeros
|
|
|
|
uint8_t n = dci_format0_sizeof(nof_prb);
|
|
|
|
uint32_t n = dci_format0_sizeof(nof_prb);
|
|
|
|
while (y - msg->data < n) {
|
|
|
|
while (y - msg->data < n) {
|
|
|
|
*y++ = 0;
|
|
|
|
*y++ = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -253,11 +253,11 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* TODO: TPC and cyclic shift for DM RS not implemented
|
|
|
|
* TODO: TPC and cyclic shift for DM RS not implemented
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint8_t nof_prb) {
|
|
|
|
int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint32_t nof_prb) {
|
|
|
|
|
|
|
|
|
|
|
|
/* pack bits */
|
|
|
|
/* pack bits */
|
|
|
|
char *y = msg->data;
|
|
|
|
char *y = msg->data;
|
|
|
|
uint8_t n_ul_hop;
|
|
|
|
uint32_t n_ul_hop;
|
|
|
|
|
|
|
|
|
|
|
|
/* Make sure it's a Format0 message */
|
|
|
|
/* Make sure it's a Format0 message */
|
|
|
|
if (msg->location.nof_bits != dci_format_sizeof(Format0, nof_prb)) {
|
|
|
|
if (msg->location.nof_bits != dci_format_sizeof(Format0, nof_prb)) {
|
|
|
@ -283,14 +283,14 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint8_t nof_prb) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* unpack RIV according to 8.1 of 36.213 */
|
|
|
|
/* unpack RIV according to 8.1 of 36.213 */
|
|
|
|
uint16_t riv = bit_unpack(&y, riv_nbits(nof_prb) - n_ul_hop);
|
|
|
|
uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - n_ul_hop);
|
|
|
|
ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start,
|
|
|
|
ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start,
|
|
|
|
nof_prb, nof_prb);
|
|
|
|
nof_prb, nof_prb);
|
|
|
|
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - n_ul_hop);
|
|
|
|
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - n_ul_hop);
|
|
|
|
data->type2_alloc.riv = riv;
|
|
|
|
data->type2_alloc.riv = riv;
|
|
|
|
|
|
|
|
|
|
|
|
/* unpack MCS according to 8.6 of 36.213 */
|
|
|
|
/* unpack MCS according to 8.6 of 36.213 */
|
|
|
|
uint8_t mcs = bit_unpack(&y, 5);
|
|
|
|
uint32_t mcs = bit_unpack(&y, 5);
|
|
|
|
|
|
|
|
|
|
|
|
data->ndi = *y++ ? true : false;
|
|
|
|
data->ndi = *y++ ? true : false;
|
|
|
|
|
|
|
|
|
|
|
@ -326,7 +326,7 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint8_t nof_prb) {
|
|
|
|
* TODO: TPC commands
|
|
|
|
* TODO: TPC commands
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
|
|
|
|
|
|
|
|
|
|
|
|
/* pack bits */
|
|
|
|
/* pack bits */
|
|
|
|
char *y = msg->data;
|
|
|
|
char *y = msg->data;
|
|
|
@ -336,8 +336,8 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Resource allocation: type0 or type 1 */
|
|
|
|
/* Resource allocation: type0 or type 1 */
|
|
|
|
uint8_t P = ra_type0_P(nof_prb);
|
|
|
|
uint32_t P = ra_type0_P(nof_prb);
|
|
|
|
uint8_t alloc_size = (uint8_t) ceilf((float) nof_prb / P);
|
|
|
|
uint32_t alloc_size = (uint32_t) ceilf((float) nof_prb / P);
|
|
|
|
switch (data->alloc_type) {
|
|
|
|
switch (data->alloc_type) {
|
|
|
|
case alloc_type0:
|
|
|
|
case alloc_type0:
|
|
|
|
bit_pack((uint32_t) data->type0_alloc.rbg_bitmask, &y, alloc_size);
|
|
|
|
bit_pack((uint32_t) data->type0_alloc.rbg_bitmask, &y, alloc_size);
|
|
|
@ -355,7 +355,7 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* pack MCS according to 7.1.7 of 36.213 */
|
|
|
|
/* pack MCS according to 7.1.7 of 36.213 */
|
|
|
|
uint8_t mcs;
|
|
|
|
uint32_t mcs;
|
|
|
|
if (data->mcs.mod == MOD_NULL) {
|
|
|
|
if (data->mcs.mod == MOD_NULL) {
|
|
|
|
mcs = data->mcs.mcs_idx;
|
|
|
|
mcs = data->mcs.mcs_idx;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -381,7 +381,7 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
*y++ = 0;
|
|
|
|
*y++ = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// Padding with zeros
|
|
|
|
// Padding with zeros
|
|
|
|
uint8_t n = dci_format1_sizeof(nof_prb);
|
|
|
|
uint32_t n = dci_format1_sizeof(nof_prb);
|
|
|
|
while (y - msg->data < n) {
|
|
|
|
while (y - msg->data < n) {
|
|
|
|
*y++ = 0;
|
|
|
|
*y++ = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -390,7 +390,7 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
return LIBLTE_SUCCESS;
|
|
|
|
return LIBLTE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
|
|
|
|
int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb) {
|
|
|
|
|
|
|
|
|
|
|
|
/* pack bits */
|
|
|
|
/* pack bits */
|
|
|
|
char *y = msg->data;
|
|
|
|
char *y = msg->data;
|
|
|
@ -408,8 +408,8 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Resource allocation: type0 or type 1 */
|
|
|
|
/* Resource allocation: type0 or type 1 */
|
|
|
|
uint8_t P = ra_type0_P(nof_prb);
|
|
|
|
uint32_t P = ra_type0_P(nof_prb);
|
|
|
|
uint8_t alloc_size = (uint8_t) ceilf((float) nof_prb / P);
|
|
|
|
uint32_t alloc_size = (uint32_t) ceilf((float) nof_prb / P);
|
|
|
|
switch (data->alloc_type) {
|
|
|
|
switch (data->alloc_type) {
|
|
|
|
case alloc_type0:
|
|
|
|
case alloc_type0:
|
|
|
|
data->type0_alloc.rbg_bitmask = bit_unpack(&y, alloc_size);
|
|
|
|
data->type0_alloc.rbg_bitmask = bit_unpack(&y, alloc_size);
|
|
|
@ -426,7 +426,7 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* unpack MCS according to 7.1.7 of 36.213 */
|
|
|
|
/* unpack MCS according to 7.1.7 of 36.213 */
|
|
|
|
uint8_t mcs = bit_unpack(&y, 5);
|
|
|
|
uint32_t mcs = bit_unpack(&y, 5);
|
|
|
|
data->mcs.mcs_idx = mcs;
|
|
|
|
data->mcs.mcs_idx = mcs;
|
|
|
|
if (ra_mcs_from_idx_dl(mcs, &data->mcs)) {
|
|
|
|
if (ra_mcs_from_idx_dl(mcs, &data->mcs)) {
|
|
|
|
fprintf(stderr, "Error getting MCS\n");
|
|
|
|
fprintf(stderr, "Error getting MCS\n");
|
|
|
@ -457,7 +457,7 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* TODO: RA procedure initiated by PDCCH, TPC commands
|
|
|
|
* TODO: RA procedure initiated by PDCCH, TPC commands
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
|
|
|
|
int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb,
|
|
|
|
bool crc_is_crnti) {
|
|
|
|
bool crc_is_crnti) {
|
|
|
|
|
|
|
|
|
|
|
|
/* pack bits */
|
|
|
|
/* pack bits */
|
|
|
@ -479,7 +479,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
|
|
|
|
return LIBLTE_ERROR;
|
|
|
|
return LIBLTE_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
uint8_t n_vrb_dl;
|
|
|
|
uint32_t n_vrb_dl;
|
|
|
|
if (crc_is_crnti && nof_prb > 50) {
|
|
|
|
if (crc_is_crnti && nof_prb > 50) {
|
|
|
|
n_vrb_dl = 16;
|
|
|
|
n_vrb_dl = 16;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -493,14 +493,14 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* pack RIV according to 7.1.6.3 of 36.213 */
|
|
|
|
/* pack RIV according to 7.1.6.3 of 36.213 */
|
|
|
|
uint16_t riv;
|
|
|
|
uint32_t riv;
|
|
|
|
if (data->type2_alloc.L_crb) {
|
|
|
|
if (data->type2_alloc.L_crb) {
|
|
|
|
riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start,
|
|
|
|
riv = ra_type2_to_riv(data->type2_alloc.L_crb, data->type2_alloc.RB_start,
|
|
|
|
nof_prb);
|
|
|
|
nof_prb);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
riv = data->type2_alloc.riv;
|
|
|
|
riv = data->type2_alloc.riv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint8_t nb_gap = 0;
|
|
|
|
uint32_t nb_gap = 0;
|
|
|
|
if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) {
|
|
|
|
if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) {
|
|
|
|
nb_gap = 1;
|
|
|
|
nb_gap = 1;
|
|
|
|
*y++ = data->type2_alloc.n_gap;
|
|
|
|
*y++ = data->type2_alloc.n_gap;
|
|
|
@ -508,13 +508,13 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
|
|
|
|
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - nb_gap);
|
|
|
|
bit_pack((uint32_t) riv, &y, riv_nbits(nof_prb) - nb_gap);
|
|
|
|
|
|
|
|
|
|
|
|
// in format1A, MCS = TBS according to 7.1.7.2 of 36.213
|
|
|
|
// in format1A, MCS = TBS according to 7.1.7.2 of 36.213
|
|
|
|
uint8_t mcs;
|
|
|
|
uint32_t mcs;
|
|
|
|
if (data->mcs.mod == MOD_NULL) {
|
|
|
|
if (data->mcs.mod == MOD_NULL) {
|
|
|
|
mcs = data->mcs.mcs_idx;
|
|
|
|
mcs = data->mcs.mcs_idx;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (data->mcs.tbs) {
|
|
|
|
if (data->mcs.tbs) {
|
|
|
|
// In format 1A, n_prb_1a is 2 or 3 if crc is not scrambled with C-RNTI
|
|
|
|
// In format 1A, n_prb_1a is 2 or 3 if crc is not scrambled with C-RNTI
|
|
|
|
uint8_t n_prb;
|
|
|
|
uint32_t n_prb;
|
|
|
|
if (!crc_is_crnti) {
|
|
|
|
if (!crc_is_crnti) {
|
|
|
|
n_prb = ra_nprb_dl(data, nof_prb);
|
|
|
|
n_prb = ra_nprb_dl(data, nof_prb);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -547,7 +547,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Padding with zeros
|
|
|
|
// Padding with zeros
|
|
|
|
uint8_t n = dci_format1A_sizeof(nof_prb);
|
|
|
|
uint32_t n = dci_format1A_sizeof(nof_prb);
|
|
|
|
while (y - msg->data < n) {
|
|
|
|
while (y - msg->data < n) {
|
|
|
|
*y++ = 0;
|
|
|
|
*y++ = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -559,7 +559,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb,
|
|
|
|
/* Unpacks DCI format 1A for compact scheduling of PDSCH words according to 36.212 5.3.3.1.3
|
|
|
|
/* Unpacks DCI format 1A for compact scheduling of PDSCH words according to 36.212 5.3.3.1.3
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
|
|
|
|
int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb,
|
|
|
|
bool crc_is_crnti) {
|
|
|
|
bool crc_is_crnti) {
|
|
|
|
|
|
|
|
|
|
|
|
/* pack bits */
|
|
|
|
/* pack bits */
|
|
|
@ -583,18 +583,18 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
|
|
|
|
data->type2_alloc.n_gap = t2_ng1;
|
|
|
|
data->type2_alloc.n_gap = t2_ng1;
|
|
|
|
|
|
|
|
|
|
|
|
/* unpack RIV according to 7.1.6.3 of 36.213 */
|
|
|
|
/* unpack RIV according to 7.1.6.3 of 36.213 */
|
|
|
|
uint8_t nb_gap = 0;
|
|
|
|
uint32_t nb_gap = 0;
|
|
|
|
if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) {
|
|
|
|
if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) {
|
|
|
|
nb_gap = 1;
|
|
|
|
nb_gap = 1;
|
|
|
|
data->type2_alloc.n_gap = *y++;
|
|
|
|
data->type2_alloc.n_gap = *y++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint8_t nof_vrb;
|
|
|
|
uint32_t nof_vrb;
|
|
|
|
if (data->type2_alloc.mode == t2_loc) {
|
|
|
|
if (data->type2_alloc.mode == t2_loc) {
|
|
|
|
nof_vrb = nof_prb;
|
|
|
|
nof_vrb = nof_prb;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
nof_vrb = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
|
|
|
|
nof_vrb = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint16_t riv = bit_unpack(&y, riv_nbits(nof_prb) - nb_gap);
|
|
|
|
uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - nb_gap);
|
|
|
|
ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start,
|
|
|
|
ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start,
|
|
|
|
nof_prb, nof_vrb);
|
|
|
|
nof_prb, nof_vrb);
|
|
|
|
data->type2_alloc.riv = riv;
|
|
|
|
data->type2_alloc.riv = riv;
|
|
|
@ -623,7 +623,7 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
data->mcs.tbs_idx = data->mcs.mcs_idx;
|
|
|
|
data->mcs.tbs_idx = data->mcs.mcs_idx;
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t n_prb;
|
|
|
|
uint32_t n_prb;
|
|
|
|
if (crc_is_crnti) {
|
|
|
|
if (crc_is_crnti) {
|
|
|
|
n_prb = ra_nprb_dl(data, nof_prb);
|
|
|
|
n_prb = ra_nprb_dl(data, nof_prb);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -638,7 +638,7 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
|
|
|
|
/* Format 1C for compact scheduling of PDSCH words
|
|
|
|
/* Format 1C for compact scheduling of PDSCH words
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
|
|
|
|
|
|
|
|
|
|
|
|
/* pack bits */
|
|
|
|
/* pack bits */
|
|
|
|
char *y = msg->data;
|
|
|
|
char *y = msg->data;
|
|
|
@ -652,12 +652,12 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
if (nof_prb >= 50) {
|
|
|
|
if (nof_prb >= 50) {
|
|
|
|
*y++ = data->type2_alloc.n_gap;
|
|
|
|
*y++ = data->type2_alloc.n_gap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint8_t n_step = ra_type2_n_rb_step(nof_prb);
|
|
|
|
uint32_t n_step = ra_type2_n_rb_step(nof_prb);
|
|
|
|
uint8_t n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
|
|
|
|
uint32_t n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
|
|
|
|
|
|
|
|
|
|
|
|
if (data->type2_alloc.L_crb > ((uint8_t) n_vrb_dl / n_step) * n_step) {
|
|
|
|
if (data->type2_alloc.L_crb > ((uint32_t) n_vrb_dl / n_step) * n_step) {
|
|
|
|
fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n",
|
|
|
|
fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n",
|
|
|
|
data->type2_alloc.L_crb, ((uint8_t) n_vrb_dl / n_step) * n_step);
|
|
|
|
data->type2_alloc.L_crb, ((uint32_t) n_vrb_dl / n_step) * n_step);
|
|
|
|
return LIBLTE_ERROR;
|
|
|
|
return LIBLTE_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (data->type2_alloc.L_crb % n_step) {
|
|
|
|
if (data->type2_alloc.L_crb % n_step) {
|
|
|
@ -668,11 +668,11 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
fprintf(stderr, "RB_start must be multiple of n_step\n");
|
|
|
|
fprintf(stderr, "RB_start must be multiple of n_step\n");
|
|
|
|
return LIBLTE_ERROR;
|
|
|
|
return LIBLTE_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint8_t L_p = data->type2_alloc.L_crb / n_step;
|
|
|
|
uint32_t L_p = data->type2_alloc.L_crb / n_step;
|
|
|
|
uint8_t RB_p = data->type2_alloc.RB_start / n_step;
|
|
|
|
uint32_t RB_p = data->type2_alloc.RB_start / n_step;
|
|
|
|
uint8_t n_vrb_p = (int) n_vrb_dl / n_step;
|
|
|
|
uint32_t n_vrb_p = (int) n_vrb_dl / n_step;
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t riv;
|
|
|
|
uint32_t riv;
|
|
|
|
if (data->type2_alloc.L_crb) {
|
|
|
|
if (data->type2_alloc.L_crb) {
|
|
|
|
riv = ra_type2_to_riv(L_p, RB_p, n_vrb_p);
|
|
|
|
riv = ra_type2_to_riv(L_p, RB_p, n_vrb_p);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -681,7 +681,7 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
bit_pack((uint32_t) riv, &y, riv_nbits((int) n_vrb_dl / n_step));
|
|
|
|
bit_pack((uint32_t) riv, &y, riv_nbits((int) n_vrb_dl / n_step));
|
|
|
|
|
|
|
|
|
|
|
|
// in format1C, MCS = TBS according to 7.1.7.2 of 36.213
|
|
|
|
// in format1C, MCS = TBS according to 7.1.7.2 of 36.213
|
|
|
|
uint8_t mcs;
|
|
|
|
uint32_t mcs;
|
|
|
|
if (data->mcs.mod == MOD_NULL) {
|
|
|
|
if (data->mcs.mod == MOD_NULL) {
|
|
|
|
mcs = data->mcs.mcs_idx;
|
|
|
|
mcs = data->mcs.mcs_idx;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -697,8 +697,8 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
return LIBLTE_SUCCESS;
|
|
|
|
return LIBLTE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
|
|
|
|
int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb) {
|
|
|
|
uint8_t L_p, RB_p;
|
|
|
|
uint32_t L_p, RB_p;
|
|
|
|
|
|
|
|
|
|
|
|
/* pack bits */
|
|
|
|
/* pack bits */
|
|
|
|
char *y = msg->data;
|
|
|
|
char *y = msg->data;
|
|
|
@ -712,11 +712,11 @@ int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
|
|
|
|
if (nof_prb >= 50) {
|
|
|
|
if (nof_prb >= 50) {
|
|
|
|
data->type2_alloc.n_gap = *y++;
|
|
|
|
data->type2_alloc.n_gap = *y++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint8_t n_step = ra_type2_n_rb_step(nof_prb);
|
|
|
|
uint32_t n_step = ra_type2_n_rb_step(nof_prb);
|
|
|
|
uint8_t n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
|
|
|
|
uint32_t n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1);
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t riv = bit_unpack(&y, riv_nbits((int) n_vrb_dl / n_step));
|
|
|
|
uint32_t riv = bit_unpack(&y, riv_nbits((int) n_vrb_dl / n_step));
|
|
|
|
uint8_t n_vrb_p = (uint8_t) n_vrb_dl / n_step;
|
|
|
|
uint32_t n_vrb_p = (uint32_t) n_vrb_dl / n_step;
|
|
|
|
|
|
|
|
|
|
|
|
ra_type2_from_riv(riv, &L_p, &RB_p, n_vrb_p, n_vrb_p);
|
|
|
|
ra_type2_from_riv(riv, &L_p, &RB_p, n_vrb_p, n_vrb_p);
|
|
|
|
data->type2_alloc.L_crb = L_p * n_step;
|
|
|
|
data->type2_alloc.L_crb = L_p * n_step;
|
|
|
@ -734,7 +734,7 @@ int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int dci_msg_pack_pdsch(ra_pdsch_t *data, dci_msg_t *msg, dci_format_t format,
|
|
|
|
int dci_msg_pack_pdsch(ra_pdsch_t *data, dci_msg_t *msg, dci_format_t format,
|
|
|
|
uint8_t nof_prb, bool crc_is_crnti) {
|
|
|
|
uint32_t nof_prb, bool crc_is_crnti) {
|
|
|
|
switch (format) {
|
|
|
|
switch (format) {
|
|
|
|
case Format1:
|
|
|
|
case Format1:
|
|
|
|
return dci_format1_pack(data, msg, nof_prb);
|
|
|
|
return dci_format1_pack(data, msg, nof_prb);
|
|
|
@ -749,7 +749,7 @@ int dci_msg_pack_pdsch(ra_pdsch_t *data, dci_msg_t *msg, dci_format_t format,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
|
|
|
|
int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb,
|
|
|
|
bool crc_is_crnti) {
|
|
|
|
bool crc_is_crnti) {
|
|
|
|
if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) {
|
|
|
|
if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) {
|
|
|
|
return dci_format1_unpack(msg, data, nof_prb);
|
|
|
|
return dci_format1_unpack(msg, data, nof_prb);
|
|
|
@ -762,11 +762,11 @@ int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int dci_msg_pack_pusch(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) {
|
|
|
|
int dci_msg_pack_pusch(ra_pusch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
|
|
|
|
return dci_format0_pack(data, msg, nof_prb);
|
|
|
|
return dci_format0_pack(data, msg, nof_prb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int dci_msg_unpack_pusch(dci_msg_t *msg, ra_pusch_t *data, uint8_t nof_prb) {
|
|
|
|
int dci_msg_unpack_pusch(dci_msg_t *msg, ra_pusch_t *data, uint32_t nof_prb) {
|
|
|
|
return dci_format0_unpack(msg, data, nof_prb);
|
|
|
|
return dci_format0_unpack(msg, data, nof_prb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -806,7 +806,7 @@ void dci_msg_type_fprint(FILE *f, dci_msg_type_t type) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, uint8_t nof_prb,
|
|
|
|
int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, uint32_t nof_prb,
|
|
|
|
uint16_t crnti) {
|
|
|
|
uint16_t crnti) {
|
|
|
|
if (msg->location.nof_bits == dci_format_sizeof(Format0, nof_prb)
|
|
|
|
if (msg->location.nof_bits == dci_format_sizeof(Format0, nof_prb)
|
|
|
|
&& !msg->data[0]) {
|
|
|
|
&& !msg->data[0]) {
|
|
|
|