Commit 0b90e899 authored by Nick Ho's avatar Nick Ho

Scheduler function completes, still has some warning to solve

parent 25f8a1bb
......@@ -1182,7 +1182,7 @@ set (MAC_SRC
${MAC_DIR}/eNB_scheduler_bch.c
${MAC_DIR}/eNB_scheduler_bch_NB_IoT.c
${MAC_DIR}/eNB_scheduler_primitives.c
${MAC_DIR}/eNB_scheduler_primitives_NB_IoT.c
${MAC_DIR}/output_handler_NB_IoT.c
${MAC_DIR}/eNB_scheduler_RA.c
${MAC_DIR}/eNB_scheduler_RA_NB_IoT.c
${MAC_DIR}/pre_processor.c
......
......@@ -545,6 +545,15 @@ typedef struct {
} eNB_MAC_INST_NB_IoT;
// actually not here, but for now put it here
typedef struct {
uint32_t bytes_in_buffer; /*!< \brief Bytes buffered in RLC protocol instance. */
uint32_t pdus_in_buffer; /*!< \brief Number of PDUs buffered in RLC protocol instance (OBSOLETE). */
uint32_t head_sdu_creation_time; /*!< \brief Head SDU creation time. */
uint32_t head_sdu_remaining_size_to_send; /*!< \brief remaining size of sdu: could be the total size or the remaining size of already segmented sdu */
boolean_t head_sdu_is_segmented; /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */
} mac_rlc_status_resp_NB_IoT_t;
// global variables
nprach_parameters_NB_IoT_t nprach_list[3];
......@@ -552,9 +561,9 @@ nprach_parameters_NB_IoT_t nprach_list[3];
//SCHEDULE_NB_IoT_t *NB_IoT_schedule;
/******MAC Global Variable********/
available_resource_tones_UL_t *available_resource_UL;
available_resource_DL_t *available_resource_DL;
available_resource_DL_t *available_resource_DL_last;
//available_resource_tones_UL_t *available_resource_UL;
//available_resource_DL_t *available_resource_DL;
//available_resource_DL_t *available_resource_DL_last;
/*
schedule_result_t *schedule_result_list_UL;
......@@ -563,78 +572,4 @@ available_resource_DL_t *available_resource_DL_last;
//DLSF Table
DLSF_INFO_t DLSF_information;
// array will be active when they are used
// 10 -> single-tone / 12 -> multi-tone
//static uint32_t max_mcs[2] = {10, 12};
// [CE level] [0 - 3] -> single-tone / [CE level] [4-7] -> multi-tone
/*static uint32_t mapped_mcs[3][8]={{1,5,9,10,3,7,11,12},
{0,3,7,10,3,7,11,12},
{0,2,6,10,0,4,8,12}};*/
//TBS table for NPUSCH transmission TS 36.213 v14.2 table Table 16.5.1.2-2:
/*static int UL_TBS_Table[14][8]=
{
{16,2,56,88,120,152,208,256},
{24,56,88,144,176,208,256,344},
{32,72,144,176,208,256,328,424},
{40,104,176,208,256,328,440,568},
{56,120,208,256,328,408,552,680},
{72,144,224,328,424,504,680,872},
{88,176,256,392,504,600,808,1000},
{104,224,328,472,584,712,1000,1224},
{120,256,392,536,680,808,1096,1384},
{136,296,456,616,776,936,1256,1544},
{144,328,504,680,872,1000,1384,1736},
{176,376,584,776,1000,1192,1608,2024},
{208,440,680,1000,1128,1352,1800,2280},
{224,488,744,1128,1256,1544,2024,2536}
};*/
//static uint32_t RU_table[8]={1,2,3,4,5,6,8,10};
//static uint32_t scheduling_delay[4]={8,16,32,64};
//static uint32_t msg3_scheduling_delay_table[4] = {12,16,32,64};
//static uint32_t ack_nack_delay[4]={13,15,17,18};
//static uint32_t R_dl_table[16]={1,2,4,8,16,32,64,128,192,256,384,512,768,1024,1536,2048};
// NB_IoT-IoT------------------
// TBS table for the case not containing SIB1-NB_IoT, Table 16.4.1.5.1-1 in TS 36.213 v14.2
/*static uint32_t TBStable_NB_IoT[14][8] ={ //[ITBS][ISF]
{16,32,56,88,120.152,208,256},
{24,56,88,144,176,208,256,344},
{32,72,144,176,208,256,328,424},
{40,104,176,208,256,328,440,568},
{56,120,208,256,328,408,552,680},
{72,144,244,328,424,504,680,872},
{88,176,256,392,504,600,808,1032},
{104,224,328,472,584,680,968,1224},
{120,256,392,536,680,808,1096,1352},
{136,296,456,616,776,936,1256,1544},
{144,328,504,680,872,1032,1384,1736},
{176,376,584,776,1000,1192,1608,2024},
{208,440,680,904,1128,1352,1800,2280},
{224,488,744,1128,1256,1544,2024,2536}
};*/
//TBS table for the case containing S1B1-NB_IoT, Table 16.4.1.5.2-1 in TS 36.213 v14.2 (Itbs = 12 ~ 15 is reserved field
//mapping ITBS to SIB1-NB_IoT
//static unsigned int TBStable_NB_IoT_SIB1[16] = {208,208,208,328,328,328,440,440,440,680,680,680};
//static int DV_table[16]={0,10,14,19,26,36,49,67,91,125,171,234,321,768,1500,1500};
/*static int BSR_table[64]= {0,10,12,14,17,19,22,26,31,36,42,49,57,67,78,91,
105,125,146,171,200,234,274,321,376,440,515,603,706,826,967,1132,
1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099,
16507,19325,22624,26487,31009,36304,42502,49759,58255,68201,79846,93479,109439,128125,150000,300000
};*/
//static int dl_rep[3] = {1, 2, 4};
//static uint32_t dci_rep[3] = {1, 2, 4};
//static uint32_t harq_rep[3] = {1, 2, 4};
#endif /*__LAYER2_MAC_DEFS_NB_IoT_H__ */
......@@ -29,21 +29,210 @@
*
*/
#include "defs_NB_IoT.h"
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
// scheduler
#define flag_css_type1 0x1
#define flag_css_type2 0x2
#define flag_uss_v 0x4
// common
#define flag_mib 0x1
#define flag_sib1 0x2
#define flag_npss 0x4
#define flag_nsss 0x8
/*function description
* top level of the scheduler, this will trigger in every subframe,
#define num_flags 2
int extend_space[num_flags] = {160, 160};
int extend_alpha_offset[num_flags] = {10, 10};
int uss_space = 320;
int uss_alpha_offset = 10;
void eNB_scheduler_computing_flag_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe, uint32_t *scheduler_flags, uint32_t *common_flags){
uint32_t subframe = abs_subframe % 10;
uint32_t frame = abs_subframe / 10;
int i;
if(subframe == 0){
*common_flags |= flag_mib;
}else if(subframe == 5){
*common_flags |= flag_npss;
}else if(subframe == 9 && (frame&0x1)==0){
*common_flags |= flag_nsss;
}else if(subframe == 4 && mac_inst->sib1_flag[frame%mac_inst->sib1_period]){
*common_flags |= flag_sib1;
}
for(i=0; i<num_flags; ++i){
if(((abs_subframe+1)%extend_space[i])==(extend_space[i]>>extend_alpha_offset[i])){
*scheduler_flags |= (0x1<<i);
}
}
//USS trigger flag
for(i=0;i<mac_inst->num_uss_list;++i)
{
//printf("[eNB Computing falg] USS trigger time %d ss start time %d\n", ((abs_subframe+1)%mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.T), mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.ss_start_uss);
if(((abs_subframe+1)%mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.T)==mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.ss_start_uss)
{
//SCHEDULE_LOG("1\n");
*scheduler_flags |= (flag_uss_v<<i);
}
}
//printf("[eNB Computing falg] scheduler_flags %X\n", *scheduler_flags);
/*
//USS trigger flag
if((abs_subframe%uss_space)==(uss_space>>uss_alpha_offset)){
*scheduler_flags |= flag_uss_v;
}
*/
}
/*function description:
* top level of the scheduler, this will trigger in every subframe,
* and determined if do the schedule by checking this current subframe is the start of the NPDCCH period or not
*/
void eNB_dlsch_ulsch_scheduler_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe){
// eNB_MAC_INST_NB_IoT *eNB = &eNB_mac_inst_NB_IoT[module_id];
int i, max_subframe, scheduler_flags, common_flags,MIB_flag,SIB1_flag;
/*Check this subframe should schedule something, set the flag*/
scheduler_flags = 0;
common_flags = 0;
MIB_flag = 0;
SIB1_flag = 0;
int h,f,sf;
int a;
//DEBUG("--------------[%04d][eNB scheduler NB-IoT] Start Scheduling------------\n", mac_inst->current_subframe);
eNB_scheduler_computing_flag_NB_IoT(mac_inst, abs_subframe, &scheduler_flags, &common_flags);
/*Update the available resource list to current state*/
//NB_IoT_maintain_available_resource(subframe, frame, hypersfn);
max_subframe = 0;
for(i=0; i<num_flags; ++i){
if(1 == (scheduler_flags&(0x1<<i))){
if(max_subframe < extend_space[i]){
max_subframe = extend_space[i];
}
}
}
if(scheduler_flags > 0){
extend_available_resource_DL(mac_inst, mac_inst->current_subframe + 1 + max_subframe);
}
maintain_available_resource(mac_inst);
/* already defined in proto_NB_IoT.h
void eNB_dlsch_ulsch_scheduler_NB_IoT(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, uint16_t hypersfn)
{
static int test=2;
if((abs_subframe % rachperiod[4]) == rachstart[0]){
add_UL_Resource();
}
//Check if type2 searching space scheduling
if((scheduler_flags&flag_css_type2)>0){
schedule_RA_NB_IoT(mac_inst);
scheduler_flags &= ~(flag_css_type2);
}
//Check if type1 searching space scheduling
if((scheduler_flags&flag_css_type1)>0){
scheduler_flags &= ~(flag_css_type1);
}
// loop all USS period
for(i=0;i<mac_inst->num_uss_list;++i)
{
if((scheduler_flags&(flag_uss_v<<i))>0){
printf("--------------[%04d][SchedulerUSS] Schedule USS list %d------------\n", mac_inst->current_subframe, (scheduler_flags&(flag_uss_v<<i))>>3);
scheduler_flags &= ~(flag_uss_v<<i);
convert_system_number(abs_subframe, &h, &f, &sf);
//DEBUG("=====t:%d======\n", mac_inst->current_subframe);
//print_available_resource_DL();
schedule_uss_NB_IoT(0, mac_inst,sf, f, h, i);
}
}
/*
//Check if UE-specific searching space scheduling
if((scheduler_flags&flag_uss_v)>0){
scheduler_flags &= ~(flag_uss_v);
convert_system_number(abs_subframe, &h, &f, &sf);
//DEBUG("=====t:%d======\n", mac_inst->current_subframe);
//print_available_resource_DL();
schedule_uss_NB_IoT(0, mac_inst,sf, f, h, 0);
}
*/
if(common_flags == flag_mib)
MIB_flag = 1;
if(common_flags == flag_sib1)
SIB1_flag = 1;
convert_system_number(abs_subframe, &h, &f, &sf);
a = output_handler(mac_inst, 0,0,h,f,sf,MIB_flag,SIB1_flag, abs_subframe);
//DEBUG("--------------[%04d][eNB scheduler NB-IoT] End Scheduling------------\n", mac_inst->current_subframe);
}
*/
void schedule_uss_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, uint32_t subframe, uint32_t frame, uint32_t hypersfn, int index_ss)
{
int32_t i;
//SCHEDULE_NB_IoT_t *scheduler = &eNB->scheduler;
mac_inst->scheduling_flag.flag_uss[0]=1;
mac_inst->scheduling_flag.flag_uss[1]=0;
mac_inst->scheduling_flag.flag_uss[2]=0;
mac_inst->scheduling_flag.num_uss_run = 0;
//search space index
//int index_ss=0;
int UE_ID;
UE_TEMPLATE_NB_IoT *UE_template_temp;
if(mac_inst->scheduling_flag.num_uss_run > 1)
{
//spectial case
}
else
{
//general case
}
UE_ID = mac_inst->UE_list_spec[index_ss].head;
//DEBUG("t=%d UE ID head %d\n", mac_inst->current_subframe,UE_ID);
while(UE_ID>-1)
{
UE_template_temp = &(mac_inst->UE_list_spec[index_ss].UE_template_NB_IoT[UE_ID]);
printf("------Start Scheduling USS UE RNTI %d------\n", UE_template_temp->rnti);
if(UE_template_temp->RRC_connected!=1)
{
printf("[schedule_uss_NB_IoT] UE ID %d RRC not connected\n", UE_ID);
printf("[%04d][USS scheduler][UE%d] rrc not connected\n", mac_inst->current_subframe, UE_template_temp->rnti);
}
else
{
printf("t=%d*******[schedule_uss_NB_IoT] schedule UE_ID %d direction %d*******%d %d %d\n", mac_inst->current_subframe, UE_ID, UE_template_temp->direction, hypersfn, frame, subframe);
printf("[%04d][USS scheduler][UE%d] ", mac_inst->current_subframe, UE_template_temp->rnti);
switch(UE_template_temp->direction)
{
//Downlink Scheduling
case 1:
printf("uss downlink scheduling.. \n");
schedule_DL_NB_IoT(0, mac_inst, UE_template_temp, hypersfn, frame, subframe);
break;
//Uplink Scheduling
case 0:
DEBUG("uss uplink scheduling.. \n");
schedule_UL_NB_IoT(mac_inst, UE_template_temp, subframe, frame, hypersfn);
break;
case -1:
printf("current idle.. \n");
default:
break;
}
//printf("----------------End Scheduling USS UE RNTI %d-------------------\n", UE_template_temp->rnti);
UE_template_temp->direction = -1;
}
UE_ID = UE_template_temp->next;
}
}
......@@ -29,8 +29,626 @@
*/
#include "defs_NB_IoT.h"
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
char str1[] = "rar_dci";
char str2[] = "rar";
char str3[] = "msg4_dci";
char str4[] = "msg4";
char str5[] = "ack_msg4";
char str6[] = "msg3_dci(retransmit)";
char str7[] = "msg3(retransmit)";
char str8[] = "msg4_dci(retransmit)";
char str9[] = "msg4(retransmit)";
char str10[] = "ack_msg4(retransmit)";
char str11[] = "msg3";
char str12[] = "msg3(retransmit)";
// 7bytes
void fill_rar_NB_IoT(
eNB_MAC_INST_NB_IoT *inst,
RA_TEMPLATE_NB_IoT *ra_template,
uint8_t msg3_schedule_delay,
uint8_t msg3_rep,
sched_temp_UL_NB_IoT_t *schedule_template
)
//------------------------------------------------------------------------------
{
uint8_t *dlsch_buffer = &ra_template->rar_buffer[0];
RA_HEADER_RAPID_NB_IoT *rarh = (RA_HEADER_RAPID_NB_IoT *)dlsch_buffer;
int i,ra_idx = -1;
uint16_t rballoc;
uint8_t mcs,TPC,ULdelay,cqireq;
for(i=0; i<7; ++i){
dlsch_buffer[i] = 0x0;
}
// subheader fixed
rarh->E = 0; // First and last RAR
rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader
rarh->RAPID = ra_template->preamble_index; // Respond to Preamble 0 only for the moment
uint8_t *rar = (uint8_t *)(dlsch_buffer+1);
// ta
ra_template->ta >>= 4;
rar[0] = (uint8_t)(ra_template->ta>>(2+4)); // 7 MSBs of timing advance + divide by 4
rar[1] = (uint8_t)(ra_template->ta<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4
// msg3 grant (15bits)
// subcarrier spacing:1 subcarrier indication:6 scheduling delay:2 msg3 repetition:3 MCS index: 3
uint8_t subcarrier_spacing = 1; // 1bit 15kHz
uint8_t subcarrier_indication = schedule_template->subcarrier_indication; // 6bits
uint8_t i_delay = msg3_schedule_delay; // 2bits
uint8_t msg3_repetition = msg3_rep;// 3bit
uint8_t mcs_index = 0;//3bit, msg3 88bits 3'b000
rar[1] |= (subcarrier_spacing<<4) | (subcarrier_indication>>3);
rar[2] = (uint8_t)(subcarrier_indication<<5) | (i_delay<<3) | msg3_repetition;
rar[3] = (mcs_index<<5)&0xe0; // maped
// tc-rnti
rar[4] = (uint8_t)(ra_template->ue_rnti>>8);
rar[5] = (uint8_t)(ra_template->ue_rnti&0xff);
}
void schedule_msg3_retransimission_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
RA_TEMPLATE_NB_IoT *msg3_nodes = mac_inst->RA_msg3_list.head;
available_resource_DL_t *dci_node, *msg3_node;
int rmax, fail, res, r;
int dci_subframe, dci_end_subframe, dci_first_subframe, num_dci_subframe;
int msg3_subframe, msg3_end_subframe;
int dci_candidate, num_candidate;
int msg3_scheduling_delay;
schedule_result_t *dci_result;//, *msg3_result;
int rep=1;
sched_temp_UL_NB_IoT_t npusch_info;
while((RA_TEMPLATE_NB_IoT *)0 != msg3_nodes){
if(msg3_nodes->wait_msg3_ack == 0){
fail=0;
// check dci resource
rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg3_nodes->ce_level].mac_npdcch_NumRepetitions_RA_NB_IoT;//32;
num_candidate = 8;//rmax / r;
r = rmax/num_candidate;
num_dci_subframe = r;
dci_subframe = mac_inst->current_subframe;
for(dci_candidate=0; dci_candidate<8; ++dci_candidate){
while(!is_dlsf(mac_inst, dci_subframe)){
++dci_subframe;
}
dci_node = (available_resource_DL_t *)check_resource_DL(mac_inst, dci_subframe, num_dci_subframe, &dci_end_subframe, &dci_first_subframe);
if((available_resource_DL_t *)0 != dci_node){
//dci_subframe += dci_candidate*num_dci_subframe;
//printf("[RA scheduler][%d][MSG3] [%x][HARQ][DCI]\tstart %3d, num %3d, end %3d\n", mac_inst->current_subframe, msg3_nodes->ue_rnti, dci_subframe, num_dci_subframe, dci_end_subframe);
break;
}
res = num_dci_subframe;
while(res != 0){ // cost lot of time to search
if(is_dlsf(mac_inst, dci_subframe)){
res--;
}
dci_subframe++;
}
}
if(8==dci_candidate){
//failed
fail|=0x1;
}
// check msg3 resource
msg3_subframe = dci_end_subframe+8;
rep = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg3_nodes->ce_level].mac_numRepetitionsPerPreambleAttempt_NB_IoT;
sched_temp_UL_NB_IoT_t npusch_info;
uint32_t Iru = 0, mcs, Nru;
uint32_t mappedMcsIndex = 4; // assume all ue supported multi-tone
mcs = mapped_mcs[msg3_nodes->ce_level][mappedMcsIndex]; // assume all ue supported multi-tone
int TBS = get_TBS_UL_NB_IoT(mcs,1,Iru);
while((TBS<11)&&(Iru<=7)){
Iru++;
TBS=get_TBS_UL_NB_IoT(mcs,1,Iru);
}
Nru = RU_table[Iru];
for(msg3_scheduling_delay=0; msg3_scheduling_delay<4; ++msg3_scheduling_delay){
if(0==Check_UL_resource(msg3_subframe+msg3_scheduling_delay_table[msg3_scheduling_delay]+1, Nru*rep, &npusch_info, 1, 0)){ //1: multi-tones 0: single-tone. 1: format 2(ack/nack) 0: format 1
//msg3_subframe += (msg3_scheduling_delay<<2);
//printf("[MSG3][%x][HARQ]\t\tstart %3d, num %3d, end %3d\n", msg3_nodes->ue_rnti, msg3_subframe, npusch_info.sf_end-msg3_subframe, npusch_info.sf_end);
break;
}
}
if(4==msg3_scheduling_delay){
//failed
fail|=0x2;
}
if(0 == fail){
msg3_nodes->wait_msg3_ack = 1;
DCIFormatN0_t *dci_n0_msg3 = (DCIFormatN0_t *)malloc(sizeof(DCIFormatN0_t));
// dci entity
dci_n0_msg3->type = 0;
dci_n0_msg3->scind = npusch_info.subcarrier_indication;
dci_n0_msg3->ResAssign = 0;
dci_n0_msg3->mcs = 0;
dci_n0_msg3->ndi = 0; // retrnasmit
dci_n0_msg3->Scheddly = msg3_scheduling_delay;
dci_n0_msg3->RepNum = rep;
dci_n0_msg3->rv = 0;
dci_n0_msg3->DCIRep = 1;//get_DCI_REP()
// for dci
dci_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
dci_result->output_subframe = dci_first_subframe;//dci_subframe;
dci_result->end_subframe = dci_end_subframe;
dci_result->sdu_length = 0;
dci_result->direction = UL;
dci_result->DCI_release = 0;
dci_result->channel = NPDCCH;
dci_result->rnti = msg3_nodes->ue_rnti;
dci_result->rnti_type = 1;
dci_result->npusch_format = 0; //useless
dci_result->R_harq = 0;
dci_result->next = (schedule_result_t *)0;
dci_result->DCI_pdu = (void *)dci_n0_msg3;
dci_result->debug_str = str6;
//simulate_rx(&simulate_rx_msg3_list, msg3_nodes->ue_rnti, npusch_info.sf_start);
// fill dci resource
fill_resource_DL(mac_inst, dci_node, dci_first_subframe, dci_end_subframe, dci_result);
// fill msg3 resource
generate_scheduling_result_UL(-1, -1, npusch_info.sf_start, npusch_info.sf_end, dci_n0_msg3, msg3_nodes->ue_rnti, str12, (void *)0); // rnti
adjust_UL_resource_list(&npusch_info);
printf("[%04d][RA scheduler][MSG3 re] MSG3DCI %d-%d MSG3 %d-%d\n", mac_inst->current_subframe, dci_first_subframe, dci_end_subframe, npusch_info.sf_start, npusch_info.sf_end );
}else{
printf("[%04d][RA scheduler][MSG3 re] fail vector %d\n", mac_inst->current_subframe, fail );
}
++msg3_nodes->msg3_retransmit_count;
}
msg3_nodes = msg3_nodes->next;
}
return ;
}
void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
RA_TEMPLATE_NB_IoT *msg2_nodes = mac_inst->RA_msg2_list.head;
RA_TEMPLATE_NB_IoT *msg3_list_tail = mac_inst->RA_msg3_list.tail;
RA_TEMPLATE_NB_IoT *migrate_node;
schedule_result_t *dci_result, *msg2_result;
DCIFormatN0_t *dci_n0;
DCIFormatN1_t *dci_n1_rar;
available_resource_DL_t *dci_node, *msg2_node, *msg3_node;
int rmax, fail, r, res;
int dci_subframe, dci_end_subframe, dci_first_subframe, num_dci_subframe;
int msg2_subframe, msg2_end_subframe, msg2_first_subframe, num_msg2_subframe;
int msg3_subframe, msg3_end_subframe;
int dci_candidate, i, num_candidate;
int msg2_i_delay;
int msg3_scheduling_delay;
static uint16_t tc_rnti = 0x0101;
int rep=1;
sched_temp_UL_NB_IoT_t npusch_info;
int fail_num = 0;
while((RA_TEMPLATE_NB_IoT *)0 != msg2_nodes){
fail=0;
rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg2_nodes->ce_level].mac_npdcch_NumRepetitions_RA_NB_IoT;//32;
num_candidate = 8;//rmax / r;
r = rmax/num_candidate;
num_dci_subframe = r;
dci_subframe = mac_inst->current_subframe;
for(dci_candidate=0; dci_candidate<num_candidate; ++dci_candidate){
while(!is_dlsf(mac_inst, dci_subframe)){
++dci_subframe;
}
dci_node = (available_resource_DL_t *)check_resource_DL(mac_inst, dci_subframe, num_dci_subframe, &dci_end_subframe, &dci_first_subframe);
if((available_resource_DL_t *)0 != dci_node){
//dci_subframe += dci_candidate*num_dci_subframe;
break;
}
res = num_dci_subframe;
while(res != 0){ // maybe would cost lots of time to search
if(is_dlsf(mac_inst, dci_subframe)){
res--;
}
dci_subframe++;
}
}
if(num_candidate==dci_candidate){
fail|=0x1;
}
// check msg2 resource
uint32_t TBS, I_tbs, I_mcs, I_sf, Nrep;
I_mcs = get_I_mcs_NB_IoT(msg2_nodes->ce_level);
I_tbs = I_mcs;
TBS = get_tbs(7, I_tbs, &I_sf); // rar 7 bytes
Nrep = dl_rep[msg2_nodes->ce_level];
num_msg2_subframe = get_num_sf(I_sf) * Nrep;
//num_msg2_subframe = 8;
msg2_i_delay = find_suit_i_delay(rmax, r, dci_candidate);
for(i=0; i<8; ++i, ++msg2_i_delay){
msg2_i_delay = (msg2_i_delay==8)?0:msg2_i_delay;
msg2_subframe = dci_end_subframe+4+get_scheduling_delay(msg2_i_delay, rmax);
msg2_node = (available_resource_DL_t *)check_resource_DL(mac_inst, msg2_subframe, num_msg2_subframe, &msg2_end_subframe, &msg2_first_subframe);
if((available_resource_DL_t *)0 != msg2_node){
break;
}
}
if(-1==msg2_i_delay){
fail|=0x2;
}
// check msg3 resource
rep = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg2_nodes->ce_level].mac_numRepetitionsPerPreambleAttempt_NB_IoT;
msg3_subframe = msg2_end_subframe;
uint32_t Iru = 0, mcs, Nru;
uint32_t mappedMcsIndex = 4; // assume all ue supported multi-tone
mcs = mapped_mcs[msg2_nodes->ce_level][mappedMcsIndex]; // assume all ue supported multi-tone
TBS = get_TBS_UL_NB_IoT(mcs,1,Iru);
while((TBS<11)&&(Iru<=7)){ // 88 bits
Iru++;
TBS=get_TBS_UL_NB_IoT(mcs,1,Iru);
}
Nru = RU_table[Iru];
for(msg3_scheduling_delay=0; msg3_scheduling_delay<4; ++msg3_scheduling_delay){
// 36.213 Table 16.3.3-1 Imcs=3'b000 Nru=4
if(0==Check_UL_resource(msg3_subframe+msg3_scheduling_delay_table[msg3_scheduling_delay]+1, Nru*rep, &npusch_info, 1, 0)){ //1: multi-tones 0: single-tone. 1: format 2(ack/nack) 0: format 1
break;
}
}
if(4==msg3_scheduling_delay){
fail|=0x4;
}
if(0 < fail){
fail_num++;
printf("[%04d][RA scheduler][MSG2] fail vector %d\n", mac_inst->current_subframe, fail);
//SCHEDULE_LOG("[%04d][RA scheduler][MSG2] rnti: %d preamble: %d fail vector %d\n", mac_inst->current_subframe, msg2_nodes->ra_rnti, msg2_nodes->preamble_index, fail);
msg2_nodes = msg2_nodes->next;
}else{
//SCHEDULE_LOG("[%04d][RA scheduler][MSG2] rnti: %d preamble: %d success\n", mac_inst->current_subframe, msg2_nodes->ra_rnti, msg2_nodes->preamble_index);
dci_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
msg2_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
dci_n0 = (DCIFormatN0_t *)malloc(sizeof(DCIFormatN0_t));
dci_n1_rar = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t));
fill_rar_NB_IoT(mac_inst, msg2_nodes, msg3_scheduling_delay, rep, &npusch_info);
msg2_nodes->wait_msg3_ack = 1;
// dci entity
dci_n1_rar->type = 1;
dci_n1_rar->orderIndicator = 0;
dci_n1_rar->Scheddly = msg2_i_delay;
dci_n1_rar->ResAssign = 0;
dci_n1_rar->mcs = 0;
dci_n1_rar->RepNum = 0; // 36.213 table 16.4.1.3-2, 8 candidates
dci_n1_rar->ndi = 0; // ndi is useless in RAR 36.212 says the feild is reserved
dci_n1_rar->HARQackRes = 0; // no HARQ procedure in RAR 36.212 says the feild is reserved
dci_n1_rar->DCIRep = 0; // 36.213 table 16.6-1 R=Rmax/8
// for dci
dci_result->output_subframe = dci_first_subframe;//dci_subframe;
dci_result->end_subframe = dci_end_subframe;
dci_result->sdu_length = 0;
dci_result->direction = DL;
dci_result->DCI_release = 0;
dci_result->channel = NPDCCH;
dci_result->rnti = msg2_nodes->ra_rnti;//ra_rnti;
dci_result->rnti_type = 1;
dci_result->npusch_format = 0; //useless
dci_result->R_harq = 0;
dci_result->next = (schedule_result_t *)0;
dci_result->DCI_pdu = (void *)dci_n1_rar;
dci_result->debug_str = &str1[0];
// for msg2
msg2_result->output_subframe = msg2_first_subframe;//msg2_subframe;
msg2_result->end_subframe = msg2_end_subframe;
msg2_result->sdu_length = 56; // rar size
msg2_result->DLSCH_pdu = msg2_nodes->rar_buffer;
msg2_result->direction = DL;
msg2_result->DCI_release = 1;
msg2_result->channel = NPDSCH;
msg2_result->rnti = msg2_nodes->ra_rnti;//ra_rnti;
msg2_result->rnti_type = 1;
msg2_result->npusch_format = 0; //useless
msg2_result->R_harq = 0;
msg2_result->next = (schedule_result_t *)0;
msg2_result->DCI_pdu = (void *)dci_n1_rar;
msg2_result->debug_str = str2;
msg2_result->rar_buffer = msg2_nodes->rar_buffer;
// for msg3(fake DCI N0)
dci_n0->type = 0;
dci_n0->scind = npusch_info.subcarrier_indication;
dci_n0->ResAssign = 0;
dci_n0->mcs = 0;
dci_n0->ndi = 1;
dci_n0->Scheddly = msg3_scheduling_delay;
dci_n0->RepNum = rep;
dci_n0->rv = 0;
dci_n0->DCIRep = 1;//get_DCI_REP()
msg2_nodes->ue_rnti = tc_rnti;
printf("[%04d][RA scheduler][MSG2] RARDCI %d-%d RAR %d-%d MSG3 %d-%d\n", mac_inst->current_subframe, dci_first_subframe, dci_end_subframe, msg2_first_subframe, msg2_end_subframe, npusch_info.sf_start, npusch_info.sf_end);
// fill dci resource
fill_resource_DL(mac_inst, dci_node, dci_first_subframe, dci_end_subframe, dci_result);
// fill msg2 resource
fill_resource_DL(mac_inst, msg2_node, msg2_first_subframe, msg2_end_subframe, msg2_result);
// fill msg3 resource
generate_scheduling_result_UL(-1, -1, npusch_info.sf_start, npusch_info.sf_end, dci_n0, tc_rnti, str11, (void *)0);
adjust_UL_resource_list(&npusch_info);
//simulate_rx(&simulate_rx_msg3_list, tc_rnti, npusch_info.sf_start);
migrate_node = msg2_nodes;
//migrate_node->ue_rnti = tc_rnti;
tc_rnti++;
msg2_nodes = msg2_nodes->next;
// maintain list
if((RA_TEMPLATE_NB_IoT *)0 == migrate_node->prev){
// first node
mac_inst->RA_msg2_list.head = migrate_node->next; // including null
}else{
// not first node
migrate_node->prev->next = migrate_node->next; // including null
}
if((RA_TEMPLATE_NB_IoT *)0 == migrate_node->next){
// last node
mac_inst->RA_msg2_list.tail = migrate_node->prev; // including null
}else{
// not last node
migrate_node->next->prev = migrate_node->prev; // including null
}
// migrate to next list
// insert to end of list
migrate_node->next = (RA_TEMPLATE_NB_IoT *)0;
migrate_node->prev = (RA_TEMPLATE_NB_IoT *)0;
if((RA_TEMPLATE_NB_IoT *)0 == mac_inst->RA_msg3_list.head){
mac_inst->RA_msg3_list.head = migrate_node;
}else{
// not empty
mac_inst->RA_msg3_list.tail->next = migrate_node;
migrate_node->prev = mac_inst->RA_msg3_list.tail;
}
mac_inst->RA_msg3_list.tail = migrate_node;
}
}
//SCHEDULE_LOG("[%04d][RA scheduler][MSG2] failed number: %d\n", mac_inst->current_subframe, fail_num);
return ;
}
// msg4 scheduling: both first time or retransmit would be scheduled in this function(msg4_list).
void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
RA_TEMPLATE_NB_IoT *msg4_nodes = mac_inst->RA_msg4_list.head, *migrate_node;
available_resource_DL_t *dci_node, *msg4_node;
int rmax, fail, r;
int dci_subframe, dci_end_subframe, dci_first_subframe, num_dci_subframe;
int msg4_subframe, msg4_end_subframe, msg4_first_subframe, num_msg4_subframe;
int harq_subframe, harq_end_subframe;
int dci_candidate, num_candidate;
int msg4_i_delay, i, res, rep;
int end_flagHARQ, HARQ_delay;
sched_temp_UL_NB_IoT_t HARQ_info;
schedule_result_t *dci_result;
schedule_result_t *msg4_result;
schedule_result_t *harq_result;
//print_available_resource_DL();
while((RA_TEMPLATE_NB_IoT *)0 != msg4_nodes){
if(msg4_nodes->wait_msg4_ack == 0){
fail=0;
// check dci resource
rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg4_nodes->ce_level].mac_npdcch_NumRepetitions_RA_NB_IoT;//32;
num_candidate = 8;//rmax / r;
r = rmax/num_candidate;
num_dci_subframe = r;
dci_subframe = mac_inst->current_subframe;
for(dci_candidate=0; dci_candidate<num_candidate; ++dci_candidate){
while(!is_dlsf(mac_inst, dci_subframe)){
++dci_subframe;
}
dci_node = (available_resource_DL_t *)check_resource_DL(mac_inst, dci_subframe, num_dci_subframe, &dci_end_subframe, &dci_first_subframe);
if((available_resource_DL_t *)0 != dci_node){
//dci_subframe += dci_candidate*num_dci_subframe;
printf("%d msg4 dci %d - %d\n", mac_inst->current_subframe, dci_first_subframe, dci_end_subframe);
break;
}
res = num_dci_subframe;
while(res != 0){ // cost lot of time to search
if(is_dlsf(mac_inst, dci_subframe)){
res--;
}
dci_subframe++;
}
}
if(num_candidate==dci_candidate){
//failed
fail|=1;
}
// check msg4 resource
rep = dl_rep[msg4_nodes->ce_level];
num_msg4_subframe = 1*rep; // 8 subframes
msg4_i_delay = find_suit_i_delay(rmax, r, dci_candidate);
for(i=msg4_i_delay; i<8; ++i){
msg4_i_delay = (msg4_i_delay==8)?0:msg4_i_delay;
msg4_subframe = dci_end_subframe+4+get_scheduling_delay(msg4_i_delay, rmax);
msg4_node = (available_resource_DL_t *)check_resource_DL(mac_inst, msg4_subframe, num_msg4_subframe*rep, &msg4_end_subframe, &msg4_first_subframe);
if((available_resource_DL_t *)0 != msg4_node){
//printf("[MSG4]\t\t\tstart %3d, num %3d, end %3d\n", msg4_subframe, num_msg4_subframe, msg4_end_subframe);
printf("%d msg4 %d - %d\n", mac_inst->current_subframe, msg4_first_subframe, msg4_end_subframe);
break;
}
}
if(8==i){
//failed
fail|=2;
}
rep = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg4_nodes->ce_level].mac_numRepetitionsPerPreambleAttempt_NB_IoT;
//print_available_UL_resource();
for(HARQ_delay=0;HARQ_delay<4;++HARQ_delay){
end_flagHARQ=Check_UL_resource(msg4_end_subframe+get_HARQ_delay(1, HARQ_delay), rep, &HARQ_info, 0, 1); // RA_template->R
if(0 == end_flagHARQ){
harq_subframe = msg4_end_subframe + get_HARQ_delay(1, HARQ_delay);
harq_end_subframe = harq_subframe + 2*rep -1;
HARQ_info.ACK_NACK_resource_field=get_resource_field_value(HARQ_info.subcarrier_indication, get_scheduling_delay(HARQ_delay, rmax));
break;
}
}
if(4 == HARQ_delay){
fail |= 4;
}
if(0==fail){
//SCHEDULE_LOG("[%04d][RA scheduler][MSG4] rnti: %d preamble: %d success\n", mac_inst->current_subframe, msg4_nodes->ra_rnti, msg4_nodes->preamble_index);
msg4_nodes->wait_msg4_ack = 1;
DCIFormatN1_t *dci_n1_msg4 = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t));
// dci entity
dci_n1_msg4->type = 1;
dci_n1_msg4->orderIndicator = 0;
dci_n1_msg4->Scheddly = msg4_i_delay;
dci_n1_msg4->ResAssign = 0;
dci_n1_msg4->mcs = 0;
dci_n1_msg4->RepNum = 1;
dci_n1_msg4->ndi = 1;
dci_n1_msg4->HARQackRes = HARQ_info.ACK_NACK_resource_field;
dci_n1_msg4->DCIRep = 1;
// for dci
dci_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
dci_result->output_subframe = dci_first_subframe;//dci_subframe;
dci_result->end_subframe = dci_end_subframe;
dci_result->sdu_length = 0;
dci_result->direction = DL;
dci_result->DCI_release = 0;
dci_result->channel = NPDCCH;
dci_result->rnti = msg4_nodes->ue_rnti;
dci_result->rnti_type = 1;
dci_result->npusch_format = 0; //useless
dci_result->R_harq = 0;
dci_result->next = (schedule_result_t *)0;
dci_result->DCI_pdu = (void *)dci_n1_msg4;
// for msg4
msg4_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
msg4_result->output_subframe = msg4_first_subframe;// msg4_subframe;
msg4_result->end_subframe = msg4_end_subframe;
msg4_result->sdu_length = 0;
msg4_result->direction = DL;
msg4_result->DCI_release = 0;
msg4_result->channel = NPDSCH;
msg4_result->rnti = msg4_nodes->ue_rnti;
msg4_result->rnti_type = 1;
msg4_result->npusch_format = 0; //useless
msg4_result->R_harq = 0;
msg4_result->next = (schedule_result_t *)0;
msg4_result->DCI_pdu = (void *)dci_n1_msg4;
harq_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
harq_result->rnti = msg4_nodes->ue_rnti;
harq_result->output_subframe = harq_subframe;
harq_result->end_subframe = harq_end_subframe;
harq_result->sdu_length = 0;
harq_result->direction = UL;
harq_result->rnti_type = 3;
harq_result->DLSCH_pdu = NULL;
harq_result->DCI_pdu = (void *)dci_n1_msg4;
harq_result->DCI_release = 1;
harq_result->channel = NPUSCH;
harq_result->next = (schedule_result_t *)0;
if(msg4_nodes->msg4_retransmit_count==0){
dci_result->debug_str = str3;
msg4_result->debug_str = str4;
harq_result->debug_str = str5;
}else{
dci_result->debug_str = str8;
msg4_result->debug_str = str9;
harq_result->debug_str = str10;
}
//simulate_rx(&simulate_rx_msg4_list, msg4_nodes->ue_rnti, harq_subframe);
//DEBUG("[%04d][RA scheduler][MSG4] UE:%x MSG4DCI %d-%d MSG4 %d-%d HARQ %d-%d\n", mac_inst->current_subframe, msg4_nodes->ue_rnti, dci_first_subframe, dci_end_subframe, msg4_first_subframe, msg4_end_subframe, HARQ_info.sf_start, HARQ_info.sf_end);
msg4_nodes->msg4_retransmit_count++;
// fill dci resource
fill_resource_DL(mac_inst, dci_node, dci_first_subframe, dci_end_subframe, dci_result);
// fill msg4 resource
fill_resource_DL(mac_inst, msg4_node, msg4_first_subframe, msg4_end_subframe, msg4_result);
// fill ack/nack resource
insert_schedule_result(&schedule_result_list_UL, harq_subframe, harq_result);
//DEBUG("check point\n");
adjust_UL_resource_list(&HARQ_info);
// active ue_list ul/dl
UE_list_NB_IoT_t *UE_list = mac_inst->UE_list_spec;
for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
if(UE_list->UE_template_NB_IoT[i].active == 1 && UE_list->UE_template_NB_IoT[i].rnti == msg4_nodes->ue_rnti){
UE_list->UE_template_NB_IoT[i].direction = rand()&1;
}
}
}else{
//DEBUG("[%04d][RA scheduler][MSG4] fail vector %d\n", mac_inst->current_subframe, fail );
//SCHEDULE_LOG("[%04d][RA scheduler][MSG4] rnti: %d preamble: %d fail vector %d\n", mac_inst->current_subframe, msg4_nodes->ra_rnti, msg4_nodes->preamble_index, fail);
}
}
msg4_nodes = msg4_nodes->next;
}
return ;
}
void schedule_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
uint32_t current_subframe = mac_inst->current_subframe;
schedule_msg3_retransimission_NB_IoT(mac_inst);
schedule_rar_NB_IoT(mac_inst);
schedule_msg4_NB_IoT(mac_inst);
return ;
}
// initiate_ra_proc here
......@@ -28,3 +28,837 @@
* @ingroup _mac
*/
#include "defs_NB_IoT.h"
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE_TEMPLATE_NB_IoT *UE_info, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start)
{
//number of candidate
int cdd_num;
//Transport block size
int TBS;
//Scheduling result buffer
sched_temp_DL_NB_IoT_t *NPDCCH_info = (sched_temp_DL_NB_IoT_t*)malloc(sizeof(sched_temp_DL_NB_IoT_t));
sched_temp_DL_NB_IoT_t *NPDSCH_info = (sched_temp_DL_NB_IoT_t*)malloc(sizeof(sched_temp_DL_NB_IoT_t));
sched_temp_UL_NB_IoT_t *HARQ_info = (sched_temp_UL_NB_IoT_t*)malloc(sizeof(sched_temp_UL_NB_IoT_t));
//DCI N1
DCIFormatN1_t *DCI_N1 = (DCIFormatN1_t*)malloc(sizeof(DCIFormatN1_t));
//RLC Status
mac_rlc_status_resp_NB_IoT_t rlc_status;
/*Index in DCI_N1*/
uint32_t I_mcs, I_tbs, I_delay, I_sf;
/*value for corresponding index*/
/*Number of subframe per repetition*/
int n_sf;
/*flag*/
int end_flagCCH=0;
int end_flagSCH=0;
int end_flagHARQ=0;
int flag_retransmission=0;
int HARQ_delay=0;
uint32_t data_size;
uint32_t mac_sdu_size;
uint8_t sdu_temp[SCH_PAYLOAD_SIZE_MAX_NB_IoT];
logical_chan_id_t logical_channel;
uint32_t subheader_length=2;
uint32_t payload_offset;
uint32_t search_space_end_sf, h_temp, f_temp, sf_temp;
I_mcs = get_I_mcs_NB_IoT(UE_info->CE_level);
I_tbs = I_mcs;
//get max TBS
TBS = get_max_tbs(I_tbs);
printf("[%04d][DLSchedulerUSS] Max TBS %d MCS index %d TBS index %d\n", mac_inst->current_subframe, TBS, I_mcs, I_tbs);
/*set UE data information*/
/*New transmission*/
if(UE_info->HARQ_round==0)
{
//Get RLC status
/*
rlc_status = mac_rlc_status_ind_NB_IoT(
module_id,
UE_info->rnti,
module_id,
frame_start,
subframe_start,
1,
0,
DCCH0_NB_IoT,
0);
data_size = rlc_status.bytes_in_buffer;
*/
data_size = 200;
}
/*Retransmission*/
else
{
data_size = UE_info->DLSCH_pdu_size;
flag_retransmission = 1;
if((UE_info->HARQ_round>0)&&(TBS<data_size))
{
printf("[%04d][DLSchedulerUSS][Fail] TBS is not enough for retransmission\n", mac_inst->current_subframe);
return;
}
}
printf("[%04d][DLSchedulerUSS] UE data size %d\n", mac_inst->current_subframe, data_size);
//Have DCCH data
if(data_size == 0)
{
printf("[%04d][DLSchedulerUSS][Fail] No data in DCCH0_NB_IoT\n", mac_inst->current_subframe);
return;
}
if(data_size>127)
{
subheader_length=3;
}
if(TBS > data_size+subheader_length)
{
TBS = get_tbs(data_size, I_tbs, &I_sf);
printf("[%04d][DLSchedulerUSS] TBS change to %d because data size is smaller than previous TBS\n", mac_inst->current_subframe, TBS);
}
search_space_end_sf=cal_num_dlsf(mac_inst, hyperSF_start, frame_start, subframe_start, &h_temp, &f_temp, &sf_temp, UE_info->R_max);
printf("[%04d][DLSchedulerUSS] Search_space_start_sf %d Search_space_end_sf %d\n", convert_system_number_sf(hyperSF_start, frame_start, subframe_start), mac_inst->current_subframe, search_space_end_sf);
/*Loop all NPDCCH candidate position*/
for(cdd_num=0;cdd_num<UE_info->R_max/UE_info->R_dci;++cdd_num)
{
//DEBUG("[%04d][DLSchedulerUSS] Candidate num %d DCI Rep %d\n", cdd_num, UE_info->R_dci);
/*Check NPDCCH Resource*/
end_flagCCH = check_resource_NPDCCH_NB_IoT(mac_inst, hyperSF_start, frame_start, subframe_start, NPDCCH_info, cdd_num, UE_info->R_dci);
//This candidate position is available
/*Check NPDSCH Resource*/
if(end_flagCCH!=-1)
{
//DEBUG("[%04d][DLSchedulerUSS] Candidate num %d allocate success\n", cdd_num);
//DEBUG("[%04d][DLSchedulerUSS] Allocate NPDCCH subframe %d to subframe %d cdd index %d\n", mac_inst->current_subframe, NPDCCH_info->sf_start, NPDCCH_info->sf_end, cdd_num);
/*
//Max DL TBS
if(TBS > data_size+subheader_length)
{
TBS = get_tbs(data_size, I_tbs, &I_sf);
DEBUG("[%04d][DLSchedulerUSS] TBS change to %d because data size is smaller than previous TBS\n", mac_inst->current_subframe, TBS);
}
*/
//Get number of subframe this UE need per repetition
n_sf = get_num_sf(I_sf);
//DEBUG("[%04d][DLSchedulerUSS] Number SF %d index SF %d\n", n_sf, I_sf);
//DEBUG("[%04d][DLSchedulerUSS] Require total %d DL SF Rep %d\n", n_sf*UE_info->R_dl, UE_info->R_dl);
//Check have enough NPDSCH resource or not
//loop 8 scheduling delay index
for(I_delay=0;I_delay<8;++I_delay)
{
if(search_space_end_sf<NPDCCH_info->sf_end+get_scheduling_delay(I_delay, UE_info->R_max)+5)
{
end_flagSCH = check_resource_NPDSCH_NB_IoT(mac_inst, NPDSCH_info, NPDCCH_info->sf_end, I_delay, UE_info->R_max, UE_info->R_dl, n_sf);
//Have available resource
/*Check HARQ resource*/
if(end_flagSCH!=-1)
{
//DEBUG("[%04d][DLSchedulerUSS] Scheduling delay index: %d value: %d + 4 allocate success\n", mac_inst->current_subframe, I_delay, get_scheduling_delay(I_delay, UE_info->R_max));
//DEBUG("[%04d][DLSchedulerUSS] Allocate NPDSCH subframe %d to subframe %d\n", mac_inst->current_subframe, NPDSCH_info->sf_start, NPDSCH_info->sf_end);
for(HARQ_delay=0;HARQ_delay<4;++HARQ_delay)
{
//DEBUG("[%04d][DLSchedulerUSS] HARQ delay %d\n", mac_inst->current_subframe,get_HARQ_delay(1, HARQ_delay) );
end_flagHARQ=Check_UL_resource(NPDSCH_info->sf_end+get_HARQ_delay(1, HARQ_delay), UE_info->R_harq, HARQ_info, 0, 1);
if(end_flagHARQ!=-1)
{
//DEBUG("[%04d][DLSchedulerUSS] Allocate HARQ feedback subframe %d to subframe %d\n", mac_inst->current_subframe, HARQ_info->sf_start, HARQ_info->sf_end);
HARQ_info->ACK_NACK_resource_field=get_resource_field_value(HARQ_info->subcarrier_indication, get_scheduling_delay(HARQ_delay, UE_info->R_max));
//toggle NDI
if(flag_retransmission==0)
{
UE_info->oldNDI_DL=(UE_info->oldNDI_DL+1)%2;
//New transmission need to request data from RLC and generate new MAC PDU
UE_info->I_mcs_dl = I_mcs;
/*
//Request data from RLC layer
rlc_status = mac_rlc_status_ind_NB_IoT(
module_id,
UE_info->rnti,
module_id,
frame_start,
subframe_start,
1,
0,
DCCH0_NB_IoT,
TBS-subheader_length);
*/
//mac_sdu_size = mac_rlc_data_req_eNB_NB_IoT(module_id, UE_info->rnti, 0, frame_start, 0, DCCH0_NB_IoT, sdu_temp);
logical_channel=DCCH0_NB_IoT;
//Generate header
//payload_offset = generate_dlsch_header_NB_IoT(UE_info->DLSCH_pdu.payload, 1, &logical_channel, &mac_sdu_size, 0, 0, TBS);
//Complete MAC PDU
//memcpy(UE_info->DLSCH_pdu.payload+payload_offset, sdu_temp, mac_sdu_size);
UE_info->DLSCH_pdu.pdu_size=TBS;
}
//SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] RNTI %d complete scheduling\n", mac_inst->current_subframe, UE_info->rnti);
//SCHEDULE_LOG("[%04d][DLSchedulerUSS] RNTI %d\n", mac_inst->current_subframe, UE_info->rnti);
//SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] Allocate NPDCCH subframe %d to subframe %d cdd index %d\n", mac_inst->current_subframe, NPDCCH_info->sf_start, NPDCCH_info->sf_end, cdd_num);
//SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] Scheduling delay index: %d value: %d + 4\n", mac_inst->current_subframe, I_delay, get_scheduling_delay(I_delay, UE_info->R_max));
//SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] Allocate NPDSCH subframe %d to subframe %d\n", mac_inst->current_subframe, NPDSCH_info->sf_start, NPDSCH_info->sf_end);
//SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] Allocate HARQ feedback subframe %d to subframe %d\n", mac_inst->current_subframe, HARQ_info->sf_start, HARQ_info->sf_end);
//DEBUG("[%04d][DLSchedulerUSS] Allocate NPDCCH subframe %d to subframe %d cdd index %d\n", mac_inst->current_subframe, NPDCCH_info->sf_start, NPDCCH_info->sf_end, cdd_num);
//DEBUG("[%04d][DLSchedulerUSS] Scheduling delay index: %d value: %d + 4\n", mac_inst->current_subframe, I_delay, get_scheduling_delay(I_delay, UE_info->R_max));
//DEBUG("[%04d][DLSchedulerUSS] Allocate NPDSCH subframe %d to subframe %d\n", mac_inst->current_subframe, NPDSCH_info->sf_start, NPDSCH_info->sf_end);
//DEBUG("[%04d][DLSchedulerUSS] Allocate HARQ feedback subframe %d to subframe %d\n", mac_inst->current_subframe, HARQ_info->sf_start, HARQ_info->sf_end);
//Store PDU in UE template for retransmission
fill_DCI_N1(DCI_N1, UE_info, I_delay, I_sf, HARQ_info->ACK_NACK_resource_field);
//DEBUG("[%04d][DLSchedulerUSS] HARQ index %d\n", HARQ_info->ACK_NACK_resource_field);
printf("[%04d][DLSchedulerUSS] DCI N1 type:%d order:%d MCS:%d HARQ index:%d R:%d RscAssign:%d scheddly:%d DCI_R:%d\n", mac_inst->current_subframe, DCI_N1->type, DCI_N1->orderIndicator, DCI_N1->mcs, DCI_N1->HARQackRes, DCI_N1->RepNum, DCI_N1->ResAssign, DCI_N1->Scheddly, DCI_N1->DCIRep);
//Generate Scheduling result for this UE
generate_scheduling_result_DL(NPDCCH_info->sf_start, NPDSCH_info->sf_start, HARQ_info->sf_start, DCI_N1, UE_info->rnti, TBS, UE_info->DLSCH_pdu.payload);
//DEBUG("[%04d][DLSchedulerUSS] finish generate scheduling result\n");
//matain DL avialable resource
maintain_resource_DL(mac_inst, NPDCCH_info, NPDSCH_info);
available_resource_DL_t *temp=available_resource_DL;
/*
while(temp!=NULL)
{
DEBUG("[%04d][DLSchedulerUSS] Available resource node subframe start %d end %d\n", mac_inst->current_subframe, temp->start_subframe, temp->end_subframe);
temp=temp->next;
}
*/
//Do maintain UL resource
adjust_UL_resource_list(HARQ_info);
printf("[%04d][DLSchedulerUSS] Complete DL scheduling\n", mac_inst->current_subframe);
//SCHEDULE_LOG("[%04d][DLSchedulerUSS] RNTI %d complete scheduling\n", mac_inst->current_subframe, UE_info->rnti);
return;
}
}
/*harq resource fail*/
if(end_flagHARQ==-1)
{
//DEBUG("[%04d][DLSchedulerUSS] [Fail]HARQ_delay %d HARQ Resource fail\n", mac_inst->current_subframe, HARQ_delay);
}
}
//DEBUG("[%04d][DLSchedulerUSS] Scheduling delay index %d allocate fail\n", mac_inst->current_subframe, I_delay);
}
}
/*NPDSCH resource fail*/
if(end_flagSCH==-1)
{
//DEBUG("[%04d][DLSchedulerUSS] [Fail]I_delay %d NPDSCH Resource fail\n", mac_inst->current_subframe, I_delay);
}
}
//DEBUG("[%04d][DLSchedulerUSS] Candidate %d no resource\n", mac_inst->current_subframe, cdd_num);
}
/*Resource allocate fail*/
if((end_flagCCH==-1)||(end_flagSCH==-1)||(end_flagHARQ==-1))
{
printf("[%04d][DLSchedulerUSS][Fail]Resource allocate fail\n", mac_inst->current_subframe);
printf("[%04d][DLSchedulerUSS][Fail]RNTI %d resource allocate fail\n", mac_inst->current_subframe, UE_info->rnti);
}
}
int check_resource_NPDCCH_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start, sched_temp_DL_NB_IoT_t *NPDCCH_info, uint32_t cdd_num, uint32_t dci_rep)
{
NPDCCH_info->sf_start = cal_num_dlsf(mac_inst, hyperSF_start, frame_start, subframe_start, &(NPDCCH_info->start_h), &(NPDCCH_info->start_f), &(NPDCCH_info->start_sf), dci_rep*cdd_num+1);
//DEBUG("[check_resource_NPDCCH_NB_IoT]abs start : %d\n", NPDCCH_info->sf_start);
return check_resource_DL_NB_IoT(mac_inst, NPDCCH_info->start_h, NPDCCH_info->start_f, NPDCCH_info->start_sf, dci_rep, NPDCCH_info);
}
int check_resource_NPDSCH_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t *NPDSCH_info, uint32_t sf_end, uint32_t I_delay, uint32_t R_max, uint32_t R_dl, uint32_t n_sf)
{
int sf_temp = sf_end+get_scheduling_delay(I_delay, R_max)+5;
while(is_dlsf(mac_inst, sf_temp)!=1)
{
++sf_temp;
}
NPDSCH_info->sf_start = sf_temp;
//transform sf into Hyper SF, Frame and subframe
convert_system_number(NPDSCH_info->sf_start,&(NPDSCH_info->start_h), &(NPDSCH_info->start_f), &(NPDSCH_info->start_sf));
//check this position available or not
return check_resource_DL_NB_IoT(mac_inst, NPDSCH_info->start_h, NPDSCH_info->start_f, NPDSCH_info->start_sf, R_dl*n_sf, NPDSCH_info);
}
/*Check the available resource is enough or not from input starting position*/
/*return 0:success\1:fail*/
int check_resource_DL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start, uint32_t dlsf_require, sched_temp_DL_NB_IoT_t *schedule_info)
{
uint32_t node_start_sf, node_end_sf;
uint32_t rsc_start_sf, rsc_end_sf;
/*calculate the last subframe number for this transmission*/
schedule_info->sf_end= cal_num_dlsf(mac_inst, hyperSF_start, frame_start, subframe_start, &(schedule_info->end_h), &(schedule_info->end_f), &(schedule_info->end_sf), dlsf_require);
//DEBUG("abs_end = %d\n", schedule_info->sf_end);
rsc_start_sf = schedule_info->sf_start;
if(schedule_info->sf_start<=schedule_info->sf_end)
{
rsc_end_sf = schedule_info->sf_end;
}
else
{
/*input position + Upper bound of subframe*/
rsc_end_sf = schedule_info->sf_end+(1024*1024*10);
}
//DEBUG("check_resource_DL_NB_IoT flag 1\n");
/*initialize*/
schedule_info->node = available_resource_DL;
//DEBUG("rsc need start subframe %d end subframe %d\n", rsc_start_sf, rsc_end_sf);
/*Check available resource nodes to find the appropriate resource position*/
while(schedule_info->node!=NULL)
{
//schedule_info->node->start_subframe <= schedule_info->sf_end
//DEBUG("check_resource_DL_NB_IoT flag 2\n");
node_start_sf = schedule_info->node->start_subframe;
if(schedule_info->node->start_subframe<=schedule_info->node->end_subframe)
{
node_end_sf = schedule_info->node->end_subframe;
}
else
{
/*input position + Upper bound of subframe*/
node_end_sf = schedule_info->node->end_subframe+(1024*1024*10);
}
//DEBUG("node start %d node end %d\n", node_start_sf, node_end_sf);
if((node_start_sf<=rsc_start_sf)&&(node_end_sf>=rsc_end_sf))
{
return 0;
}
schedule_info->node = schedule_info->node->next;
}
//DEBUG("check_resource_DL_NB_IoT flag 3\n");
return -1;
}
uint32_t generate_dlsch_header_NB_IoT(uint8_t *pdu, uint32_t num_sdu, logical_chan_id_t *logical_channel, uint32_t *sdu_length, uint8_t flag_drx, uint8_t flag_ta, uint32_t TBS)
{
int i;
uint32_t total_sdu_size=0;
//number of control element
uint32_t num_ce=0;
uint32_t num_subheader=0;
uint32_t num_sdu_L_15;
int32_t padding_size;
uint8_t flag_end_padding=0;
SCH_SUBHEADER_FIXED_NB_IoT *mac_header=(SCH_SUBHEADER_FIXED_NB_IoT*)pdu;
uint32_t offset=0;
for(i=0;i<num_sdu;++i)
{
printf("index %d sdu size %d\n", i, sdu_length[i]);
if(sdu_length[i]>127)
{
num_sdu_L_15++;
}
total_sdu_size+=sdu_length[i];
}
if(flag_drx==1)
num_ce++;
if(flag_ta==1)
num_ce++;
num_subheader=num_ce+num_sdu;
padding_size = TBS-total_sdu_size-num_ce;
if(padding_size<0)
{
printf("[ERROR]TBS less than require subheader and control element\n");
return -1;
}
printf("total SDU size %d\n", total_sdu_size);
printf("padding size %d\n", padding_size);
if(padding_size>2)
{
flag_end_padding=1;
}
if((padding_size<=2)&&(padding_size>0))
{
mac_header->LCID=PADDING;
mac_header->E=1;
mac_header->F2=0;
mac_header->R=0;
mac_header++;
offset++;
}
if(padding_size==2)
{
mac_header->LCID=PADDING;
mac_header->E=1;
mac_header->F2=0;
mac_header->R=0;
mac_header++;
offset++;
}
if(flag_drx==1)
{
mac_header->LCID=DRX_COMMAND;
mac_header->E=1;
mac_header->F2=0;
mac_header->R=0;
mac_header++;
num_subheader--;
offset++;
}
for(i=0;i<num_sdu;++i)
{
if((num_subheader==1)&&(flag_end_padding!=1))
{
mac_header->E=0;
mac_header->LCID = logical_channel[i];
mac_header->F2=0;
mac_header->R=0;
offset++;
DEBUG("last sdu\n");
}
else
{
if(sdu_length[i]<128)
{
((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->LCID = logical_channel[i];
((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->F2=0;
((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->R=0;
((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->E=1;
((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->F=0;
((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->L=(uint8_t)sdu_length[i];
num_subheader--;
mac_header+=2;
offset+=2;
}
else
{
((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->LCID = logical_channel[i];
((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->F2=0;
((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->R=0;
((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->F=1;
((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->E=1;
((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->L_MSB=(uint8_t)(sdu_length[i]/256);
((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->L_LSB=(uint8_t)(sdu_length[i]%256);
mac_header+=3;
num_subheader--;
offset+=3;
}
}
}
if(flag_end_padding==1)
{
mac_header->LCID=PADDING;
mac_header->E=0;
mac_header->F2=0;
mac_header->R=0;
mac_header++;
offset++;
}
return offset;
}
void fill_DCI_N1(DCIFormatN1_t *DCI_N1, UE_TEMPLATE_NB_IoT *UE_info, uint32_t scheddly, uint32_t I_sf, uint32_t I_harq)
{
DCI_N1->type=1;
DCI_N1->orderIndicator = 0;
DCI_N1->Scheddly = scheddly;
DCI_N1->ResAssign = I_sf;
DCI_N1->mcs = UE_info->I_mcs_dl;
DCI_N1->RepNum = get_index_Rep_dl(UE_info->R_dl);
DCI_N1->HARQackRes = I_harq;
//DCI_N1->DCIRep = 3-UE_info->R_max/UE_info->R_dci/2;
DCI_N1->DCIRep = UE_info->R_dci;
}
void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subframe, uint32_t HARQ_subframe, DCIFormatN1_t *DCI_pdu, rnti_t rnti, uint32_t TBS, uint8_t *DLSCH_pdu)
{
// create the schedule result node for this time transmission
schedule_result_t *NPDCCH_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
schedule_result_t *NPDSCH_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
schedule_result_t *HARQ_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
schedule_result_t *tmp, *tmp1;
/*fill NPDCCH result*/
NPDCCH_result->rnti=rnti;
NPDCCH_result->output_subframe = DCI_subframe;
NPDCCH_result->sdu_length = TBS;
NPDCCH_result->direction = 1;
NPDCCH_result->rnti_type = 3;
NPDCCH_result->DLSCH_pdu = NULL;
NPDCCH_result->DCI_pdu = DCI_pdu;
NPDCCH_result->DCI_release = 0;
NPDCCH_result->channel = NPDCCH;
NPDCCH_result->next = NULL;
/*fill NPDSCH result*/
NPDSCH_result->rnti=rnti;
NPDSCH_result->output_subframe = NPDSCH_subframe;
NPDSCH_result->sdu_length = TBS;
//NPDSCH_result->DLSCH_pdu = DLSCH_pdu;
NPDSCH_result->DLSCH_pdu = NULL;
NPDSCH_result->direction = 1;
NPDSCH_result->rnti_type = 3;
NPDSCH_result->DCI_pdu = DCI_pdu;
NPDSCH_result->DCI_release = 0;
NPDSCH_result->channel = NPDSCH;
NPDSCH_result->next = NULL;
/*fill HARQ result*/
HARQ_result->rnti=rnti;
HARQ_result->output_subframe = HARQ_subframe;
HARQ_result->sdu_length = 0;
HARQ_result->direction = 1;
HARQ_result->rnti_type = 3;
HARQ_result->DLSCH_pdu = NULL;
HARQ_result->DCI_pdu = DCI_pdu;
HARQ_result->DCI_release = 1;
HARQ_result->channel = NPUSCH;
HARQ_result->npusch_format = 1;
HARQ_result->next = NULL;
//DEBUG("[generate_scheduling_result_DL] Generate NPDCCH node\n");
/*NPDCCH scheduling result*/
// be the first node of the DL scheduling result
tmp = NULL;
tmp1 = NULL;
if(schedule_result_list_DL == NULL)
{
//schedule_result_list_DL = (schedule_result_t*)malloc(sizeof(schedule_result_t));
schedule_result_list_DL = NPDCCH_result;
printf("[generate_scheduling_result_DL] Generate NPDCCH node at head\n");
}
else
{
tmp = schedule_result_list_DL;
while(tmp!=NULL)
{
if(DCI_subframe < tmp->output_subframe)
{
break;
}
tmp1 = tmp;
tmp = tmp->next;
//DEBUG("[generate_scheduling_result_DL] node output subframe %d at NPDCCH part\n", tmp->output_subframe);
}
/*tail*/
if(tmp==NULL)
{
tmp1->next = NPDCCH_result;
}
else
{
NPDCCH_result->next = tmp;
if(tmp1)
{
tmp1->next = NPDCCH_result;
}
else
{
schedule_result_list_DL = NPDCCH_result;
}
}
}
//DEBUG("[generate_scheduling_result_DL] Generate NPDCSH node\n");
/*NPDSCH scheduling result*/
tmp1 = NULL;
tmp = schedule_result_list_DL;
while(tmp!=NULL)
{
if(NPDSCH_subframe < tmp->output_subframe)
{
break;
}
//DEBUG("[generate_scheduling_result_DL] node output subframe %d at NPDSCH part\n", tmp->output_subframe);
tmp1 = tmp;
tmp = tmp->next;
}
if(tmp==NULL)
{
tmp1->next = NPDSCH_result;
}
else
{
NPDSCH_result->next = tmp;
if(tmp1)
{
tmp1->next = NPDSCH_result;
}
else
{
schedule_result_list_DL = NPDSCH_result;
}
}
//DEBUG("[generate_scheduling_result_DL] Generate HARQ node\n");
/*HARQ scheduling result*/
// be the first node of UL
// be the first node of UL
tmp1 = NULL;
if(schedule_result_list_UL == NULL)
{
//schedule_result_list_UL = (schedule_result_t*)malloc(sizeof(schedule_result_t));
schedule_result_list_UL = HARQ_result;
}
else
{
tmp = schedule_result_list_UL;
while(tmp!=NULL)
{
if(HARQ_subframe < tmp->output_subframe)
{
break;
}
//DEBUG("[generate_scheduling_result_DL] node output subframe %d at HARQ part\n", tmp->output_subframe);
tmp1 = tmp;
tmp = tmp->next;
}
if(tmp==NULL)
{
tmp1->next = HARQ_result;
}
else
{
HARQ_result->next = tmp;
if(tmp1)
{
tmp1->next = HARQ_result;
}else
{
schedule_result_list_UL = HARQ_result;
}
}
}
/*
DEBUG("---[generate_scheduling_result_DL] schedule result after generate---\n");
tmp = schedule_result_list_DL;
while(tmp!=NULL)
{
DEBUG("[generate_scheduling_result_DL] node output subframe %d\n", tmp->output_subframe);
tmp = tmp->next;
}
*/
}
void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t *NPDCCH_info, sched_temp_DL_NB_IoT_t *NPDSCH_info)
{
available_resource_DL_t *temp;
uint8_t flag_same=0;
int align_left;
int align_right;
int H_temp, f_temp, sf_temp;
int H_temp_r, f_temp_r, sf_temp_r;
if(NPDSCH_info==NULL)
{
/****Maintain NPDCCH node*******/
// divided into two node
// keep one node(align left or right)
// delete node
convert_system_number(NPDCCH_info->node->start_subframe, &H_temp, &f_temp, &sf_temp);
//align_left = (calculate_DLSF(mac_inst, NPDCCH_info->node->start_subframe, NPDCCH_info->sf_start) == 0);
align_left=(cal_num_dlsf(mac_inst, H_temp, f_temp, sf_temp, &H_temp_r, &f_temp_r, &sf_temp_r, 1)==NPDCCH_info->sf_start);
align_right = ((calculate_DLSF(mac_inst, NPDCCH_info->sf_end, NPDCCH_info->node->end_subframe) == 0)||(NPDCCH_info->sf_end==NPDCCH_info->node->end_subframe));
//align_left = (calculate_DLSF(mac_inst, NPDCCH_info->node->start_subframe, NPDCCH_info->sf_start) == 0);
//DEBUG("[maintain_resource_DL] align left %d align right %d\n", align_left, align_right);
switch(align_left+align_right)
{
case 0:
// divided into two node
temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
temp->next = NPDCCH_info->node->next;
temp->prev = NPDCCH_info->node;
NPDCCH_info->node->next = temp;
temp->start_subframe = NPDCCH_info->sf_end+1;
temp->end_subframe = NPDCCH_info->node->end_subframe;
NPDCCH_info->node->end_subframe = NPDCCH_info->sf_start - 1;
break;
case 1:
// keep one node
if(align_left)
{
NPDCCH_info->node->start_subframe = NPDCCH_info->sf_end+1;
}
else
{
NPDCCH_info->node->end_subframe = NPDCCH_info->sf_start-1 ;
}
break;
case 2:
// delete
if(NPDCCH_info->node->prev==NULL)
{
available_resource_DL = NPDCCH_info->node->next;
}
else
{
NPDCCH_info->node->prev->next = NPDCCH_info->node->next;
if(NPDCCH_info->node->next!=NULL)
{
NPDCCH_info->node->next->prev = NPDCCH_info->node->prev;
}
}
free(NPDCCH_info->node);
break;
default:
//error
break;
free(NPDCCH_info);
}
}
else
{
if(NPDCCH_info->node==NPDSCH_info->node)
{
flag_same=1;
printf("[%04d][maintain_resource_DL] NPDCCH and NPDSCH using the same node\n", mac_inst->current_subframe);
}
/****Maintain NPDCCH node*******/
// divided into two node
// keep one node(align left or right)
// delete node
convert_system_number(NPDCCH_info->node->start_subframe, &H_temp, &f_temp, &sf_temp);
//align_left = (calculate_DLSF(mac_inst, NPDCCH_info->node->start_subframe, NPDCCH_info->sf_start) == 0);
align_left=(cal_num_dlsf(mac_inst, H_temp, f_temp, sf_temp, &H_temp_r, &f_temp_r, &sf_temp_r, 1)==NPDCCH_info->sf_start);
align_right = ((calculate_DLSF(mac_inst, NPDCCH_info->sf_end, NPDCCH_info->node->end_subframe) == 0)||(NPDCCH_info->sf_end==NPDCCH_info->node->end_subframe));
//DEBUG("[maintain_resource_DL] align left %d align right %d\n", align_left, align_right);
switch(align_left+align_right)
{
case 0:
// divided into two node
temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
// calvin added
if((available_resource_DL_t *)0 == NPDCCH_info->node->next){
available_resource_DL_last = temp;
}
temp->next = NPDCCH_info->node->next;
temp->prev = NPDCCH_info->node;
NPDCCH_info->node->next = temp;
temp->start_subframe = NPDCCH_info->sf_end+1;
temp->end_subframe = NPDCCH_info->node->end_subframe;
NPDCCH_info->node->end_subframe = NPDCCH_info->sf_start - 1;
if(flag_same==1)
{
NPDSCH_info->node = temp;
}
break;
case 1:
// keep one node
if(align_left)
{
NPDCCH_info->node->start_subframe = NPDCCH_info->sf_end+1;
printf("[%04d][maintain_resource_DL] NPDCCH keep one node\n", mac_inst->current_subframe);
}
else
{
NPDCCH_info->node->end_subframe = NPDCCH_info->sf_start-1 ;
}
break;
case 2:
// delete
printf("[%04d][maintain_resource_DL] NPDCCH delete node\n", mac_inst->current_subframe);
// calvin add
if((available_resource_DL_t *)0 == NPDCCH_info->node->next){
available_resource_DL_last = NPDCCH_info->node->prev;
}
if(NPDCCH_info->node->prev==NULL)
{
available_resource_DL = NPDCCH_info->node->next;
}
else
{
NPDCCH_info->node->prev->next = NPDCCH_info->node->next;
if(NPDCCH_info->node->next!=NULL)
{
NPDCCH_info->node->next->prev = NPDCCH_info->node->prev;
}
}
free(NPDCCH_info->node);
break;
default:
//error
break;
}
/****Maintain NPDSCH node*******/
align_left = (calculate_DLSF(mac_inst, NPDSCH_info->node->start_subframe, NPDSCH_info->sf_start) == 0);
align_right = ((calculate_DLSF(mac_inst, NPDSCH_info->sf_end, NPDSCH_info->node->end_subframe) == 0)||(NPDSCH_info->sf_end==NPDSCH_info->node->end_subframe));
switch(align_left+align_right)
{
case 0:
// divided into two node
temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
// calvin added
if((available_resource_DL_t *)0 == NPDSCH_info->node->next){
available_resource_DL_last = temp;
}
temp->next = NPDSCH_info->node->next;
temp->prev = NPDSCH_info->node;
NPDSCH_info->node->next = temp;
temp->start_subframe = NPDSCH_info->sf_end+1;
temp->end_subframe = NPDSCH_info->node->end_subframe;
NPDSCH_info->node->end_subframe = NPDSCH_info->sf_start - 1;
break;
case 1:
// keep one node
if(align_left)
{
NPDSCH_info->node->start_subframe = NPDSCH_info->sf_end+1;
}
else
{
NPDSCH_info->node->end_subframe = NPDSCH_info->sf_start-1 ;
}
break;
case 2:
// delete
// calvin added
if((available_resource_DL_t *)0 == NPDSCH_info->node->next){
available_resource_DL_last = NPDSCH_info->node->prev;
}
if(NPDSCH_info->node->prev==NULL)
{
available_resource_DL = NPDSCH_info->node->next;
}
else
{
NPDSCH_info->node->prev->next = NPDSCH_info->node->next;
if(NPDSCH_info->node->next!=NULL)
{
NPDSCH_info->node->next->prev = NPDSCH_info->node->prev;
}
}
free(NPDSCH_info->node);
break;
default:
//error
break;
}
free(NPDCCH_info);
free(NPDSCH_info);
}
}
uint8_t get_index_Rep_dl(uint16_t R)
{
int i;
if(R<=128)
{
for(i=0;i<16;++i)
{
if(R==R_dl_table[i])
{
return i;
}
}
printf("[get_index_Rep] error\n");
}
}
\ No newline at end of file
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file eNB_scheduler_primitives.c
* \brief primitives used by eNB for BCH, RACH, ULSCH, DLSCH scheduling
* \author Navid Nikaein and Raymond Knopp
* \date 2010 - 2014
* \email: navid.nikaein@eurecom.fr
* \version 1.0
* @ingroup _mac
*/
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file eNB_scheduler_ulsch.c
* \brief eNB procedures for the ULSCH transport channel
* \author Navid Nikaein and Raymond Knopp
......@@ -29,4 +8,409 @@
*/
#include "defs_NB_IoT.h"
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
char str20[] = "DCI_uss";
char str21[] = "DATA_uss";
// scheduling UL
int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info,uint32_t subframe, uint32_t frame, uint32_t H_SFN){
int i,ndi = 0,check_DCI_result = 0,check_UL_result = 0,candidate;
uint32_t DL_end;
//Scheduling resource temp buffer
sched_temp_DL_NB_IoT_t *NPDCCH_info = (sched_temp_DL_NB_IoT_t*)malloc(sizeof(sched_temp_DL_NB_IoT_t));
candidate = UE_info->R_max/UE_info->R_dci;
uint32_t mcs = max_mcs[UE_info->multi_tone];
uint32_t mappedMcsIndex=UE_info->PHR+(4 * UE_info->multi_tone);
int TBS = 0;
int Iru = 0, Nru, I_rep,N_rep,total_ru;
int dly = 0,uplink_time = 0;
TBS=get_TBS_UL_NB_IoT(mcs,UE_info->multi_tone,Iru);
sched_temp_UL_NB_IoT_t *NPUSCH_info = (sched_temp_UL_NB_IoT_t*)malloc(sizeof(sched_temp_UL_NB_IoT_t));
DCIFormatN0_t *DCI_N0 = (DCIFormatN0_t*)malloc(sizeof(DCIFormatN0_t));
available_resource_DL_t *node;
// setting of the NDI
if(UE_info->HARQ_round == 0)
{
ndi = 1-UE_info->oldNDI_UL;
UE_info->oldNDI_UL=ndi;
}
for (i = 0; i < candidate; i++)
{
/*step 1 : Check DL resource is available for DCI N0 or not*/
check_DCI_result = check_resource_NPDCCH_NB_IoT(mac_inst,H_SFN, frame, subframe, NPDCCH_info, i, UE_info->R_dci);
//node = check_resource_DL(mac_inst,);
//just use to check when there is no DL function
//NPDCCH_info->sf_start = H_SFN*10240+frame*10 +subframe + i * UE_info->R_dci;
//NPDCCH_info->sf_end = NPDCCH_info->sf_start + (i+1) * UE_info->R_dci;
//DEBUG("UE : %5d, NPDCCH result: %d ,NPDCCH start: %d,NPDCCH end : %d\n",UE_info->rnti,check_DCI_result,NPDCCH_info->sf_start,NPDCCH_info->sf_end);
if( check_DCI_result != -1)
{
/*step 2 : Determine MCS / TBS / REP / RU number*/
/*while((mapped_mcs[UE_info->CE_level][mappedMcsIndex]< mcs)||((TBS>UE_info->ul_total_buffer)&&(mcs>=0)))
{
--mcs;
TBS=get_TBS_UL(mcs,UE_info->multi_tone,Iru);
}*/
mcs = mapped_mcs[UE_info->CE_level][mappedMcsIndex];
while((TBS<UE_info->ul_total_buffer)&&(Iru<=7))
{
Iru++;
TBS=get_TBS_UL_NB_IoT(mcs,UE_info->multi_tone,Iru);
}
//DEBUG("TBS : %d UL_buffer: %d\n", TBS, UE_info->ul_total_buffer);
Nru = RU_table[Iru];
DL_end = NPDCCH_info->sf_end;
N_rep = get_N_REP(UE_info->CE_level);
I_rep = get_I_REP(N_rep);
total_ru = Nru * N_rep;
printf("[%04d][UL scheduler][UE:%05d] Multi-tone:%d,MCS:%d,TBS:%d,UL_buffer:%d,DL_start:%d,DL_end:%d,N_rep:%d,N_ru:%d,Total_ru:%d\n", mac_inst->current_subframe,UE_info->rnti,UE_info->multi_tone,mcs,TBS,UE_info->ul_total_buffer,NPDCCH_info->sf_start,DL_end,N_rep,Nru,total_ru);
/*step 3 Check UL resource for Uplink data*/
// we will loop the scheduling delay here
for(dly=0;dly<4;dly++)
{
uplink_time = DL_end +scheduling_delay[dly];
check_UL_result = Check_UL_resource(uplink_time,total_ru, NPUSCH_info, UE_info->multi_tone, 0);
if (check_UL_result != -1)
{
// step 4 : generate DCI content
DCI_N0->type = 0;
DCI_N0->scind = NPUSCH_info->subcarrier_indication;
DCI_N0->ResAssign = Iru;
DCI_N0->mcs = mcs;
DCI_N0->ndi = ndi;
DCI_N0->Scheddly = dly;
DCI_N0->RepNum = I_rep;
DCI_N0->rv = (UE_info->HARQ_round%2==0)?0:1; // rv will loop 0 & 2
DCI_N0->DCIRep = get_DCI_REP(UE_info->R_dci,UE_info->R_max);
printf("[%04d][UL scheduler][UE:%05d] DCI content = scind : %d ResAssign : %d mcs : %d ndi : %d scheddly : %d RepNum : %d rv : %d DCIRep : %d\n", mac_inst->current_subframe,UE_info->rnti,DCI_N0->scind,DCI_N0->ResAssign,DCI_N0->mcs,DCI_N0->ndi,DCI_N0->Scheddly,DCI_N0->RepNum,DCI_N0->rv,DCI_N0->DCIRep);
// step 5 resource allocation and generate scheduling result
generate_scheduling_result_UL(NPDCCH_info->sf_start, NPDCCH_info->sf_end,NPUSCH_info->sf_start, NPUSCH_info->sf_end,DCI_N0,UE_info->rnti, str20, str21);
//fill_resource_DL();
maintain_resource_DL(mac_inst,NPDCCH_info,NULL);
adjust_UL_resource_list(NPUSCH_info);
return 0;
}
}
}
/*break now, we only loop one candidiate*/
//break;
}
printf("[%04d][UL scheduler][UE:%05d] there is no available UL resource\n", mac_inst->current_subframe, UE_info->rnti);
return -1;
}
int single_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int fmt2_flag)
{
available_resource_UL_t *single_node_tmp;
uint32_t uplink_time_end;
if(fmt2_flag == 0)
// 16 * 0.5 (slot) = 8 subframe
uplink_time_end = uplink_time + total_ru*8 -1;
else
// 4 * 0.5 (slot) = 2 subframe
uplink_time_end = uplink_time + total_ru*2 -1;
//check first list of single tone
single_node_tmp = available_resource_UL->singletone1_Head;
while(single_node_tmp!=NULL)
{
if (uplink_time >= single_node_tmp->start_subframe)
{
if ( uplink_time_end <= single_node_tmp->end_subframe)
{
NPUSCH_info->sf_end = uplink_time_end;
NPUSCH_info->sf_start = uplink_time;
NPUSCH_info->tone = singletone1;
NPUSCH_info->subcarrier_indication = 0 ; // Isc when single tone : 0-2
NPUSCH_info->node = single_node_tmp;
printf("[UL scheduler] Use uplink resource single tone 1, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
return 0;
}
}
single_node_tmp = single_node_tmp->next;
}
//check second list of single tone
single_node_tmp = available_resource_UL->singletone2_Head;
while(single_node_tmp!=NULL)
{
if (uplink_time >= single_node_tmp->start_subframe)
{
if ( uplink_time_end <= single_node_tmp->end_subframe)
{
NPUSCH_info->sf_end = uplink_time_end;
NPUSCH_info->sf_start = uplink_time;
NPUSCH_info->tone = singletone2;
NPUSCH_info->subcarrier_indication = 1 ; // Isc when single tone : 0-2
NPUSCH_info->node = single_node_tmp;
printf("[UL scheduler] Use uplink resource single tone 2, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
return 0;
}
}
single_node_tmp = single_node_tmp->next;
}
//check third list of single tone
single_node_tmp = available_resource_UL->singletone3_Head;
while(single_node_tmp!=NULL)
{
if (uplink_time >= single_node_tmp->start_subframe)
{
if ( uplink_time_end <= single_node_tmp->end_subframe)
{
NPUSCH_info->sf_end = uplink_time_end;
NPUSCH_info->sf_start = uplink_time;
NPUSCH_info->tone = singletone3;
NPUSCH_info->subcarrier_indication = 2 ; // Isc when single tone : 0-2
NPUSCH_info->node = single_node_tmp;
printf("[UL scheduler]Use uplink resource single tone 3, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
return 0;
}
}
single_node_tmp = single_node_tmp->next;
}
//DEBUG("[UL scheduler][singletone]no proper resource for this allocation\n");
return -1;
}
int multi_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info)
{
available_resource_UL_t *Next_Node;
int single_tone_result = -1;
uint32_t uplink_time_end;
/*This checking order may result in the different of the resource optimization*/
/*check 6 tones first*/
Next_Node = available_resource_UL->sixtone_Head;
// 4 * 0.5 (slot) = 2 subframe
uplink_time_end = uplink_time + total_ru*2 -1;
while(Next_Node!=NULL)
{
if (uplink_time >= Next_Node->start_subframe)
{
if ( uplink_time_end <= Next_Node->end_subframe)
{
NPUSCH_info->sf_end = uplink_time_end;
NPUSCH_info->sf_start = uplink_time;
NPUSCH_info->tone = sixtone;
NPUSCH_info->subcarrier_indication = 17 ; // Isc when 6 tone : 6 - 12
NPUSCH_info->node = Next_Node;
printf("[UL scheduler] Use uplink resource six tone, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
return 0;
}
}
Next_Node = Next_Node->next;
}
/*check 3 tones*/
Next_Node = available_resource_UL->threetone_Head;
// 8 * 0.5 (slot) = 4 subframe
uplink_time_end = uplink_time + total_ru * 4 -1;
while(Next_Node!=NULL)
{
if (uplink_time >= Next_Node->start_subframe)
{
if ( uplink_time_end <= Next_Node->end_subframe)
{
NPUSCH_info->sf_end = uplink_time_end;
NPUSCH_info->sf_start = uplink_time;
NPUSCH_info->tone = threetone;
NPUSCH_info->subcarrier_indication = 13 ; // Isc when 3 tone : 3-5
NPUSCH_info->node = Next_Node;
printf("[UL scheduler] Use uplink resource three tone, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
return 0;
}
}
Next_Node = Next_Node->next;
}
/*if there is no multi-tone resource, try to allocate the single tone resource*/
single_tone_result = single_tone_ru_allocation(uplink_time,total_ru,NPUSCH_info,0);
if(single_tone_result == 0)
return 0;
//DEBUG("[UL scheduler][multi_tone]there is no available UL resource !\n");
return -1;
}
int Check_UL_resource(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int multi_tone, int fmt2_flag)
{
int i, result =-1;
if(fmt2_flag ==0)
{
if(multi_tone == 1)
result = multi_tone_ru_allocation(uplink_time, total_ru, NPUSCH_info);
else if(multi_tone == 0)
result = single_tone_ru_allocation(uplink_time, total_ru, NPUSCH_info,0);
}else if (fmt2_flag == 1)
{
result = single_tone_ru_allocation(uplink_time, total_ru, NPUSCH_info, 1);
printf("harq result %d, time:%d total ru:%d\n", result, uplink_time, total_ru);
//if(result == 0)
//NPUSCH_info->ACK_NACK_resource_field = get_resource_field_value(NPUSCH_info->subcarrier_indication,ack_nack_delay[i]);
//DEBUG("[UL scheduler] There is available resource for ACK / NACK\n");
}
if(result == 0)
{
return 0;
}
//DEBUG("[UL scheduler] no available UL resource\n");
return -1;
}
void generate_scheduling_result_UL(int32_t DCI_subframe, int32_t DCI_end_subframe, uint32_t UL_subframe, uint32_t UL_end_subframe, DCIFormatN0_t *DCI_pdu, rnti_t rnti, uint8_t *ul_debug_str, uint8_t *dl_debug_str){
// create the schedule result node for this time transmission
schedule_result_t *UL_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
schedule_result_t *DL_result;
schedule_result_t *tmp1, *tmp;
UL_result->direction = UL;
UL_result->output_subframe = UL_subframe;
UL_result->end_subframe = UL_end_subframe;
UL_result->DCI_pdu = DCI_pdu;
UL_result->npusch_format = 0;
UL_result->DCI_release = 1;
UL_result->channel = NPUSCH;
UL_result->rnti = rnti;
UL_result->next = NULL;
UL_result->debug_str = ul_debug_str;
if(-1 == DCI_subframe){
printf("[UL scheduler][UE:%05d] UL_result = output subframe : %d\n", rnti, UL_result->output_subframe);
}else{
DL_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
DL_result->output_subframe = DCI_subframe;
DL_result->end_subframe = DCI_end_subframe;
DL_result->DCI_pdu = DCI_pdu;
DL_result->DCI_release = 0;
DL_result->direction = UL;
DL_result->channel = NPDCCH;
DL_result->rnti = rnti;
DL_result->next = NULL;
DL_result->debug_str = dl_debug_str;
insert_schedule_result(&schedule_result_list_DL, DCI_subframe, DL_result);
printf("[UL scheduler][UE:%05d] DL_result = output subframe : %d UL_result = output subframe : %d\n", rnti, DL_result->output_subframe,UL_result->output_subframe);
}
tmp1 = NULL;
// be the first node of UL
if(schedule_result_list_UL == NULL)
{
//schedule_result_list_UL = (schedule_result_t*)malloc(sizeof(schedule_result_t));
schedule_result_list_UL = UL_result;
}else
{
tmp = schedule_result_list_UL;
while(tmp!=NULL)
{
if(UL_subframe < tmp->output_subframe)
{
break;
}
tmp1 = tmp;
tmp = tmp->next;
}
if(tmp==NULL)
{
tmp1->next = UL_result;
}
else
{
UL_result->next = tmp;
if(tmp1){
tmp1->next = UL_result;
}else{
schedule_result_list_UL = UL_result;
}
}
}
}
void adjust_UL_resource_list(sched_temp_UL_NB_IoT_t *NPUSCH_info)
{
available_resource_UL_t *temp;
available_resource_UL_t *node = NPUSCH_info->node;
// divided into two node
// keep one node(align left or right)
// delete node
int align_left = (node->start_subframe==NPUSCH_info->sf_start);
int align_right = (node->end_subframe==NPUSCH_info->sf_end);
switch(align_left+align_right){
case 0:
// divided into two node
temp = (available_resource_UL_t *)malloc(sizeof(available_resource_UL_t));
temp->next = node->next;
node->next = temp;
temp->start_subframe = NPUSCH_info->sf_end +1;
temp->end_subframe = node->end_subframe;
node->end_subframe = NPUSCH_info->sf_start - 1;
break;
case 1:
// keep one node
if(align_left){
node->start_subframe = NPUSCH_info->sf_end +1;
}else{
node->end_subframe = NPUSCH_info->sf_start - 1 ;
}
break;
case 2:
// delete
node->prev->next = node->next;
node->next->prev = node->prev;
free(node);
break;
default:
//error
break;
}
// free(NPUSCH_info);
}
\ No newline at end of file
......@@ -108,6 +108,51 @@ extern available_resource_DL_t *available_resource_DL_last;
extern schedule_result_t *schedule_result_list_UL;
extern schedule_result_t *schedule_result_list_DL;
// array will be active when they are used
// 10 -> single-tone / 12 -> multi-tone
extern const uint32_t max_mcs[2];
// [CE level] [0 - 3] -> single-tone / [CE level] [4-7] -> multi-tone
extern const uint32_t mapped_mcs[3][8];
//TBS table for NPUSCH transmission TS 36.213 v14.2 table Table 16.5.1.2-2:
extern const int UL_TBS_Table[14][8];
extern const int rachperiod[8];
extern const int rachstart[8];
extern const int rachrepeat[8];
extern const int rachscofst[7];
extern const int rachnumsc[4];
extern const uint32_t RU_table[8];
extern const uint32_t scheduling_delay[4];
extern const uint32_t msg3_scheduling_delay_table[4];
extern const uint32_t ack_nack_delay[4];
extern const uint32_t R_dl_table[16];
// TBS table for the case not containing SIB1-NB_IoT, Table 16.4.1.5.1-1 in TS 36.213 v14.2
extern const uint32_t MAC_TBStable_NB_IoT[14][8];
//TBS table for the case containing S1B1-NB_IoT, Table 16.4.1.5.2-1 in TS 36.213 v14.2 (Itbs = 12 ~ 15 is reserved field
//mapping ITBS to SIB1-NB_IoT
extern const unsigned int MAC_TBStable_NB_IoT_SIB1[16];
//static int DV_table[16]={0,10,14,19,26,36,49,67,91,125,171,234,321,768,1500,1500};
/*static int BSR_table[64]= {0,10,12,14,17,19,22,26,31,36,42,49,57,67,78,91,
105,125,146,171,200,234,274,321,376,440,515,603,706,826,967,1132,
1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099,
16507,19325,22624,26487,31009,36304,42502,49759,58255,68201,79846,93479,109439,128125,150000,300000
};*/
extern const int dl_rep[3];
extern const uint32_t dci_rep[3];
extern const uint32_t harq_rep[3];
#endif //DEF_H
......
......@@ -236,8 +236,6 @@ int l2_init_eNB_NB_IoT()
init_mac_NB_IoT(mac_inst);
return(1);
}
......@@ -37,7 +37,35 @@
* @{
*/
/*for NB-IoT*/
// main schedule functions
void eNB_scheduler_computing_flag_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe, uint32_t *scheduler_flags, uint32_t *common_flags);
/*function description:
* top level of the scheduler, this will trigger in every subframe,
* and determined if do the schedule by checking this current subframe is the start of the NPDCCH period or not
*/
void eNB_dlsch_ulsch_scheduler_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe);
void schedule_sibs_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, int start_subframe1);
void schedule_uss_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, uint32_t subframe, uint32_t frame, uint32_t hypersfn, int index_ss);
void schedule_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
void schedule_msg3_retransimission_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info,uint32_t subframe, uint32_t frame, uint32_t H_SFN);
void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE_TEMPLATE_NB_IoT *UE_info, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start);
int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_id, uint32_t hypersfn, uint32_t frame, uint32_t subframe, uint8_t MIB_flag, uint8_t SIB1_flag, uint32_t current_time);
/*Scheduler resource/environment setting*/
void init_tool_sib1(eNB_MAC_INST_NB_IoT *mac_inst);
......@@ -61,17 +89,93 @@ void Initialize_Resource(void);
void extend_available_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int max_subframe);
//Transfrom source into hyperSF, Frame, Subframe format
void convert_system_number(uint32_t source_sf,uint32_t *hyperSF, uint32_t *frame, uint32_t *subframe);
uint32_t convert_system_number_sf(uint32_t hyperSF, uint32_t frame, uint32_t subframe);
void rrc_mac_config_req_NB_IoT(rrc_config_NB_IoT_t *mac_config,
uint8_t mib_flag,
uint8_t sib_flag,
uint8_t ded_flag,
uint8_t ue_list_ded_num);
// schedule functinons
void schedule_sibs_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, int start_subframe1);
// schedule helper functinons
void fill_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, available_resource_DL_t *node, int start_subframe, int end_subframe, schedule_result_t *new_node);
available_resource_DL_t *check_sibs_resource(eNB_MAC_INST_NB_IoT *mac_inst, int check_start_subframe, int check_end_subframe, int num_subframe, int *residual_subframe, int *out_last_subframe, int *out_first_subframe);
uint32_t calculate_DLSF(eNB_MAC_INST_NB_IoT *mac_inst, int abs_start_subframe, int abs_end_subframe);
// check_subframe must be DLSF, you can use is_dlsf() to check before call function
available_resource_DL_t *check_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int check_subframe, int num_subframes, int *out_last_subframe, int *out_first_subframe);
void maintain_available_resource(eNB_MAC_INST_NB_IoT *mac_inst);
int multi_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info);
int single_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int fmt2_flag);
int Check_UL_resource(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int multi_tone, int fmt2_flag);
void insert_schedule_result(schedule_result_t **list, int subframe, schedule_result_t *node);
void adjust_UL_resource_list(sched_temp_UL_NB_IoT_t *NPUSCH_info);
void generate_scheduling_result_UL(int32_t DCI_subframe, int32_t DCI_end_subframe, uint32_t UL_subframe, uint32_t UL_end_subframe, DCIFormatN0_t *DCI, rnti_t rnti, uint8_t *ul_debug_str, uint8_t *dl_debug_str);
uint32_t get_I_mcs_NB_IoT(int CE_level);
int get_TBS_UL_NB_IoT(uint32_t mcs,uint32_t multi_tone,int Iru);
// DL TBS
uint32_t get_tbs(uint32_t data_size, uint32_t I_tbs, uint32_t *I_sf);
uint32_t get_max_tbs(uint32_t I_tbs);
uint32_t get_num_sf(uint32_t I_sf);
uint16_t find_suit_i_delay(uint32_t rmax, uint32_t r, uint32_t dci_candidate);
uint32_t get_scheduling_delay(uint32_t I_delay, uint32_t R_max);
uint32_t get_HARQ_delay(int subcarrier_spacing, uint32_t HARQ_delay_index);
int get_resource_field_value(int subcarrier, int k0);
void fill_rar_NB_IoT(eNB_MAC_INST_NB_IoT *inst, RA_TEMPLATE_NB_IoT *ra_template, uint8_t msg3_schedule_delay, uint8_t msg3_rep, sched_temp_UL_NB_IoT_t *schedule_template);
uint32_t cal_num_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF, uint32_t frame, uint32_t subframe, uint32_t* hyperSF_result, uint32_t* frame_result, uint32_t* subframe_result, uint32_t num_dlsf_require);
int check_resource_NPDCCH_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start, sched_temp_DL_NB_IoT_t *NPDCCH_info, uint32_t cdd_num, uint32_t dci_rep);
int check_resource_NPDSCH_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t *NPDSCH_info, uint32_t sf_end, uint32_t I_delay, uint32_t R_max, uint32_t R_dl, uint32_t n_sf);
int check_resource_DL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start, uint32_t dlsf_require, sched_temp_DL_NB_IoT_t *schedule_info);
void fill_DCI_N1(DCIFormatN1_t *DCI_N1, UE_TEMPLATE_NB_IoT *UE_info, uint32_t scheddly, uint32_t I_sf, uint32_t I_harq);
uint32_t generate_dlsch_header_NB_IoT(uint8_t *pdu, uint32_t num_sdu, logical_chan_id_t *logical_channel, uint32_t *sdu_length, uint8_t flag_drx, uint8_t flag_ta, uint32_t TBS);
void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subframe, uint32_t HARQ_subframe, DCIFormatN1_t *DCI_pdu, rnti_t rnti, uint32_t TBS, uint8_t *DLSCH_pdu);
void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t *NPDCCH_info, sched_temp_DL_NB_IoT_t *NPDSCH_info);
int get_N_REP(int CE_level);
int get_I_REP(int N_rep);
int get_DCI_REP(uint32_t R,uint32_t R_max);
int get_I_TBS_NB_IoT(int x,int y);
uint8_t get_index_Rep_dl(uint16_t R);
//debug function
void print_available_resource_DL(void);
void print_available_UL_resource(void);
#endif
......@@ -2,18 +2,6 @@
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
int rachperiod[8]={40,80,160,240,320,640,1280,2560};
int rachstart[8]={8,16,32,64,128,256,512,1024};
int rachrepeat[8]={1,2,4,8,16,32,64,128};
//int rawindow[8]={2,3,4,5,6,7,8,10}; // unit PP
//int rmax[12]={1,2,4,8,16,32,64,128,256,512,1024,2048};
//double gvalue[8]={1.5,2,4,8,16,32,48,64};
//int candidate[4]={1,2,4,8};
//double pdcchoffset[4]={0,0.125,0.25,0.375};
//int dlrepeat[16]={1,2,4,8,16,32,64,128,192,256,384,512,768,1024,1536,2048};
int rachscofst[7]={0,12,24,36,2,18,34};
int rachnumsc[4]={12,24,36,48};
void init_tool_sib1(eNB_MAC_INST_NB_IoT *mac_inst){
int i, j;
......@@ -411,4 +399,478 @@ uint32_t calculate_DLSF(eNB_MAC_INST_NB_IoT *mac_inst, int abs_start_subframe, i
}
}
return num_dlsf;
}
void maintain_available_resource(eNB_MAC_INST_NB_IoT *mac_inst){
available_resource_DL_t *pfree;
if(mac_inst->current_subframe >= available_resource_DL->end_subframe){
//DEBUG("[maintain before kill]=====t:%d=end:%d====%p\n", mac_inst->current_subframe, available_resource_DL->end_subframe, available_resource_DL->next);
//print_available_resource_DL();
pfree = available_resource_DL;
available_resource_DL = available_resource_DL->next;
available_resource_DL->prev = (available_resource_DL_t *)0;
free((available_resource_DL_t *)pfree);
//DEBUG("[maintain after kill]=====t:%d=====\n", mac_inst->current_subframe);
//print_available_resource_DL();
}else{
available_resource_DL->start_subframe = mac_inst->current_subframe;
}
return ;
}
// check_subframe must be DLSF, you can use is_dlsf() to check before call function
available_resource_DL_t *check_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int check_subframe, int num_subframes, int *out_last_subframe, int *out_first_subframe){
available_resource_DL_t *pt;
pt = available_resource_DL;
int end_subframe = check_subframe + num_subframes - 1;
int diff_gap;
while((available_resource_DL_t *)0 != pt){
if(pt->start_subframe <= check_subframe && pt->end_subframe >= check_subframe){
break;
}
pt = pt->next;
}
if((available_resource_DL_t *)0 == pt){
return (available_resource_DL_t *)0;
}else{
if(num_subframes <= calculate_DLSF(mac_inst, check_subframe, pt->end_subframe)){
diff_gap = num_subframes - calculate_DLSF(mac_inst, check_subframe, end_subframe);
while(diff_gap){
++end_subframe;
if(is_dlsf(mac_inst, end_subframe)){
--diff_gap;
}
}
*out_last_subframe = end_subframe;
while(!is_dlsf(mac_inst, check_subframe)){
++check_subframe;
}
*out_first_subframe = check_subframe;
return pt;
}else{
return (available_resource_DL_t *)0;
}
}
}
int get_I_TBS_NB_IoT(int x,int y)
{
int I_TBS = 0;
if(y==1) I_TBS=x;
else
{
if(x==1) I_TBS=2;
else if(x==2) I_TBS=1;
else
{
I_TBS=x;
}
}
return I_TBS;
}
int get_TBS_UL_NB_IoT(uint32_t mcs,uint32_t multi_tone,int Iru)
{
int TBS;
uint32_t I_TBS=get_I_TBS_NB_IoT(mcs,multi_tone);
TBS=UL_TBS_Table[I_TBS][Iru];
//if((TBS==0)||(Iru>7))
//{
//--Iru;
//}
//TBS=UL_TBS_Table[I_TBS][Iru];
return TBS>>3;
}
void insert_schedule_result(schedule_result_t **list, int subframe, schedule_result_t *node){
schedule_result_t *tmp, *tmp1;
if((schedule_result_t *)0 == *list){
*list = node;
}else{
tmp = *list;
tmp1 = (schedule_result_t *)0;
while((schedule_result_t *)0 != tmp){
if(subframe < tmp->output_subframe){
break;
}
tmp1 = tmp;
tmp = tmp->next;
}
if((schedule_result_t *)0 == tmp){
tmp1->next = node;
}else{
node->next = tmp;
if(tmp1){
tmp1->next = node;
}else{
*list = node;
}
}
}
}
void print_available_resource_DL(void){
available_resource_DL_t *pt;
pt = available_resource_DL;
int i=0;
printf("=== print available resource ===\n");
while(pt){
printf("[%2d] %p %3d-%3d\n", i, pt, pt->start_subframe, pt->end_subframe);
pt = pt->next;
}
}
/*Get MCS index*/
uint32_t get_I_mcs_NB_IoT(int CE_level)
{
if(CE_level==0)
{
return 13;
}
else if(CE_level==1)
{
return 8;
}
else
{
return 2;
}
}
uint32_t get_tbs(uint32_t data_size, uint32_t I_tbs, uint32_t *I_sf)
{
for((*I_sf)=0;(*I_sf)<8;++(*I_sf))
{
//DEBUG("[get_tbs]TBS %d SF index %d\n", MAC_TBStable_NB_IoT[I_tbs][(*I_sf)], *I_sf);
if(MAC_TBStable_NB_IoT[I_tbs][(*I_sf)]>=data_size*8)
{
return MAC_TBStable_NB_IoT[I_tbs][(*I_sf)]/8;
}
}
printf("error\n");
return 0;
}
uint32_t get_num_sf(uint32_t I_sf)
{
if(I_sf==6)
{
return 8;
}
else if(I_sf==7)
{
return 10;
}
else
{
return I_sf+1;
}
}
uint16_t find_suit_i_delay(uint32_t rmax, uint32_t r, uint32_t dci_candidate){
uint32_t i;
uint32_t num_candidates = rmax / r;
uint32_t left_candidates = num_candidates - dci_candidate - 1; // 0-7
uint32_t resource_gap = left_candidates * r;
resource_gap = ((resource_gap * 10)>>3); // x1.125
for(i=0;i<8;++i){
if(resource_gap <= get_scheduling_delay(i, rmax)){
return i;
}
}
return 0;
}
uint32_t get_scheduling_delay(uint32_t I_delay, uint32_t R_max)
{
if(I_delay==0)
{
return 0;
}
else
{
if(R_max<128)
{
if(I_delay<=4)
return 4*I_delay;
else
return (uint32_t)(2<<I_delay);//pow(2, I_delay);
}
else
{
return (uint32_t)(16<<(I_delay-1));//*pow(2, I_delay-1);
}
}
}
/*Subcarrier_spacing 0:3.75kHz \ 1 : 15kHz*/
uint32_t get_HARQ_delay(int subcarrier_spacing, uint32_t HARQ_delay_index)
{
if(subcarrier_spacing==1)
{
if(HARQ_delay_index==0)
return 13;
else if(HARQ_delay_index==1)
return 15;
else if(HARQ_delay_index==2)
return 17;
else
return 18;
}
else
{
if((HARQ_delay_index==0)&&(HARQ_delay_index==1))
return 13;
else
return 21;
}
}
int get_resource_field_value(int subcarrier, int k0)
{
int value = 0;
if (k0 == 13)
value = subcarrier;
else if (k0 == 15)
value = subcarrier + 4;
else if (k0 == 17)
value = subcarrier + 8;
else if (k0 == 18)
value = subcarrier + 12;
return value;
}
//Transfrom source into hyperSF, Frame, Subframe format
void convert_system_number(uint32_t source_sf,uint32_t *hyperSF, uint32_t *frame, uint32_t *subframe)
{
*hyperSF = (source_sf/10)/1024;
*frame = (source_sf/10)%1024;
*subframe = (source_sf%1024)%10;
}
uint32_t get_max_tbs(uint32_t I_tbs)
{
return MAC_TBStable_NB_IoT[I_tbs][7]/8;
}
//convert hyperSF, Frame, Subframe format into subframe unit
uint32_t convert_system_number_sf(uint32_t hyperSF, uint32_t frame, uint32_t subframe)
{
return hyperSF*1024*10+frame*10+subframe;
}
/*input start position amd num_dlsf DL subframe, caculate the last subframe number*/
uint32_t cal_num_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF, uint32_t frame, uint32_t subframe, uint32_t* hyperSF_result, uint32_t* frame_result, uint32_t* subframe_result, uint32_t num_dlsf_require)
{
uint16_t sf_dlsf_index;
uint16_t dlsf_num_temp;
uint32_t abs_sf_start = 0;
uint32_t abs_sf_end = 0;
uint8_t period_count=0;
uint8_t shift_flag=0;
uint8_t scale_flag=0;
abs_sf_start=convert_system_number_sf(hyperSF, frame, subframe);
sf_dlsf_index = abs_sf_start%2560%(mac_inst->sib1_period*10);
dlsf_num_temp = DLSF_information.sf_to_dlsf_table[sf_dlsf_index];
//DEBUG("[cal_num_dlsf]sf_dlsf_index %d dlsf_num_temp %d\n", sf_dlsf_index, dlsf_num_temp);
while(num_dlsf_require>DLSF_information.num_dlsf_per_period)
{
period_count++;
num_dlsf_require-=DLSF_information.num_dlsf_per_period;
}
abs_sf_end = abs_sf_start+period_count*mac_inst->sib1_period*10;
//DEBUG("[cal_num_dlsf]abs_sf_end %d after loop\n", abs_sf_end);
if(num_dlsf_require>DLSF_information.num_dlsf_per_period-dlsf_num_temp+1)
{
if(is_dlsf(mac_inst, sf_dlsf_index)==1)
{
num_dlsf_require-=DLSF_information.num_dlsf_per_period-dlsf_num_temp+1;
}
else
{
num_dlsf_require-=DLSF_information.num_dlsf_per_period-dlsf_num_temp;
}
abs_sf_end+=mac_inst->sib1_period*10-abs_sf_end%(mac_inst->sib1_period*10);
dlsf_num_temp = 0;
scale_flag = 1;
//DEBUG("[cal_num_dlsf]abs_sf_end %d after scale\n", abs_sf_end);
}
//DEBUG("[cal_num_dlsf]num_dlsf_require remain %d\n", num_dlsf_require);
if(num_dlsf_require!=0)
{
if(scale_flag!=1)
{
if(is_dlsf(mac_inst, abs_sf_end)==1)
{
shift_flag = 1;
}
}
if(abs_sf_end%(mac_inst->sib1_period*10)!=0)
{
abs_sf_end-=abs_sf_end%(mac_inst->sib1_period*10);
//DEBUG("[cal_num_dlsf] abs_sf_end is %d mod period = %d\n", abs_sf_end, abs_sf_end%(mac_inst->sib1_NB_IoT_sched_config.sib1_period*10));
}
if(shift_flag==1)
{
abs_sf_end +=DLSF_information.dlsf_to_sf_table[dlsf_num_temp+num_dlsf_require-2];
}
else
{
abs_sf_end +=DLSF_information.dlsf_to_sf_table[dlsf_num_temp+num_dlsf_require-1];
}
//DEBUG("[cal_num_dlsf]2 DLSF_information.dlsf_to_sf_table = %d dlsf index %d\n", DLSF_information.dlsf_to_sf_table[num_dlsf_require], num_dlsf_require);
}
//DEBUG("[cal_num_dlsf]abs_sf_end %d\n", abs_sf_end);
convert_system_number(abs_sf_end, hyperSF_result, frame_result, subframe_result);
//DEBUG("[cal_num_dlsf]h %d f %d end %d\n", *hyperSF_result, *frame_result, *subframe_result);
return abs_sf_end;
}
int get_N_REP(int CE_level)
{
int N_rep= 0;
if(CE_level == 0)
{
N_rep = (nprach_list)->numRepetitionsPerPreambleAttempt;
}else if (CE_level == 1)
{
N_rep = (nprach_list+1)->numRepetitionsPerPreambleAttempt;
}else if (CE_level == 2)
{
N_rep = (nprach_list+2)->numRepetitionsPerPreambleAttempt;
}else
{
printf("unknown CE level!\n");
return -1;
}
return N_rep;
}
int get_I_REP(int N_rep)
{
int i;
for(i = 0; i < 8;i++)
{
if(N_rep == rachrepeat[i])
return i;
}
printf("unknown repetition value!\n");
return -1;
}
int get_DCI_REP(uint32_t R,uint32_t R_max)
{
int value = -1;
if (R_max == 1)
{
if(R == 1)
{
value =0;
}
}else if (R_max == 2)
{
if(R == 1)
value = 0;
if(R == 2)
value = 1;
}else if (R_max == 4)
{
if(R == 1)
value = 0;
if(R == 2)
value = 1;
if(R == 4)
value = 2;
}else if (R_max >= 8)
{
if(R == R_max/8)
value = 0;
if(R == R_max/4)
value = 1;
if(R == R_max/2)
value = 2;
if(R == R_max)
value = 3;
}
return value;
}
void print_available_UL_resource(void){
int sixtone_num=0;
int threetone_num=0;
int singletone1_num=0;
int singletone2_num=0;
int singletone3_num=0;
available_resource_UL_t *available_resource;
///sixtone
available_resource = available_resource_UL->sixtone_Head;
while(available_resource!=NULL)
{
sixtone_num++;
printf("[sixtone][Node %d] start %d , end %d\n",sixtone_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
///threetone
available_resource = available_resource_UL->threetone_Head;
while(available_resource!=NULL)
{
threetone_num++;
printf("[threetone][Node %d] start %d, end %d\n",threetone_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
///singletone1
available_resource = available_resource_UL->singletone1_Head;
while(available_resource!=NULL)
{
singletone1_num++;
printf("[singletone1][Node %d] start %d, end %d\n",singletone1_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
///singletone1
available_resource = available_resource_UL->singletone2_Head;
while(available_resource!=NULL)
{
singletone2_num++;
printf("[singletone2][Node %d] start %d, end %d\n",singletone2_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
///singletone1
available_resource = available_resource_UL->singletone3_Head;
while(available_resource!=NULL)
{
singletone3_num++;
printf("[singletone3][Node %d] start %d, end %d\n",singletone3_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
}
\ No newline at end of file
......@@ -54,9 +54,87 @@ schedule_result_t *schedule_result_list_UL;
schedule_result_t *schedule_result_list_DL;
available_resource_DL_t *available_resource_DL;
available_resource_tones_UL_t *available_resource_UL;
available_resource_DL_t *available_resource_DL_last;
//should be utilized in: schedule_RA_NB_IoT,rx_sdu_NB_IoT, mac_top_init_NB_IoT,
uint8_t Is_rrc_registered_NB_IoT;
// array will be active when they are used
// 10 -> single-tone / 12 -> multi-tone
const uint32_t max_mcs[2] = {10, 12};
// [CE level] [0 - 3] -> single-tone / [CE level] [4-7] -> multi-tone
const uint32_t mapped_mcs[3][8]={{1,5,9,10,3,7,11,12},
{0,3,7,10,3,7,11,12},
{0,2,6,10,0,4,8,12}};
//TBS table for NPUSCH transmission TS 36.213 v14.2 table Table 16.5.1.2-2:
const int UL_TBS_Table[14][8]=
{
{16,2,56,88,120,152,208,256},
{24,56,88,144,176,208,256,344},
{32,72,144,176,208,256,328,424},
{40,104,176,208,256,328,440,568},
{56,120,208,256,328,408,552,680},
{72,144,224,328,424,504,680,872},
{88,176,256,392,504,600,808,1000},
{104,224,328,472,584,712,1000,1224},
{120,256,392,536,680,808,1096,1384},
{136,296,456,616,776,936,1256,1544},
{144,328,504,680,872,1000,1384,1736},
{176,376,584,776,1000,1192,1608,2024},
{208,440,680,1000,1128,1352,1800,2280},
{224,488,744,1128,1256,1544,2024,2536}
};
const int rachperiod[8]={40,80,160,240,320,640,1280,2560};
const int rachstart[8]={8,16,32,64,128,256,512,1024};
const int rachrepeat[8]={1,2,4,8,16,32,64,128};
const int rachscofst[7]={0,12,24,36,2,18,34};
const int rachnumsc[4]={12,24,36,48};
const uint32_t RU_table[8]={1,2,3,4,5,6,8,10};
const uint32_t scheduling_delay[4]={8,16,32,64};
const uint32_t msg3_scheduling_delay_table[4] = {12,16,32,64};
const uint32_t ack_nack_delay[4]={13,15,17,18};
const uint32_t R_dl_table[16]={1,2,4,8,16,32,64,128,192,256,384,512,768,1024,1536,2048};
// TBS table for the case not containing SIB1-NB_IoT, Table 16.4.1.5.1-1 in TS 36.213 v14.2
const uint32_t MAC_TBStable_NB_IoT[14][8] ={ //[ITBS][ISF]
{16,32,56,88,120.152,208,256},
{24,56,88,144,176,208,256,344},
{32,72,144,176,208,256,328,424},
{40,104,176,208,256,328,440,568},
{56,120,208,256,328,408,552,680},
{72,144,244,328,424,504,680,872},
{88,176,256,392,504,600,808,1032},
{104,224,328,472,584,680,968,1224},
{120,256,392,536,680,808,1096,1352},
{136,296,456,616,776,936,1256,1544},
{144,328,504,680,872,1032,1384,1736},
{176,376,584,776,1000,1192,1608,2024},
{208,440,680,904,1128,1352,1800,2280},
{224,488,744,1128,1256,1544,2024,2536}
};
//TBS table for the case containing S1B1-NB_IoT, Table 16.4.1.5.2-1 in TS 36.213 v14.2 (Itbs = 12 ~ 15 is reserved field
//mapping ITBS to SIB1-NB_IoT
const unsigned int MAC_TBStable_NB_IoT_SIB1[16] = {208,208,208,328,328,328,440,440,440,680,680,680};
//static int DV_table[16]={0,10,14,19,26,36,49,67,91,125,171,234,321,768,1500,1500};
/*static int BSR_table[64]= {0,10,12,14,17,19,22,26,31,36,42,49,57,67,78,91,
105,125,146,171,200,234,274,321,376,440,515,603,706,826,967,1132,
1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099,
16507,19325,22624,26487,31009,36304,42502,49759,58255,68201,79846,93479,109439,128125,150000,300000
};*/
const int dl_rep[3] = {1, 2, 4};
const uint32_t dci_rep[3] = {1, 2, 4};
const uint32_t harq_rep[3] = {1, 2, 4};
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment