Commit aa9e906b authored by Nick Ho's avatar Nick Ho

scheduler test with USRP

parent 96e4e6f4
......@@ -428,7 +428,7 @@ void rrc_mac_config_req_NB_IoT(
mac_config->sib1_NB_IoT_sched_config.starting_rf = (intptr_t)(sib1_NB_IoT->si_RadioFrameOffset_r13);
mac_config->sib1_NB_IoT_sched_config.starting_rf = *(sib1_NB_IoT->si_RadioFrameOffset_r13);
mac_config->si_window_length = sib1_NB_IoT->si_WindowLength_r13;
......@@ -580,7 +580,7 @@ void rrc_mac_config_req_NB_IoT(
//return 0;
//init_mac_NB_IoT(mac_inst);
init_mac_NB_IoT(mac_inst);
LOG_I(MAC,"[NB-IoT] Init_MAC done\n");
......
......@@ -23,11 +23,13 @@
#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
#include "config_NB_IoT.h"
#define sim_end_time 100000
// MAC definition
#define MAX_FRAME 0xfffff
#define MAX(a, b) ((a>b)?a:b)
#define NUM_FRAME 0x100000
#define MAX_SUBFRAME 10485760
#define MAX(a, b) (((a)>(b))?(a):(b))
// RA-RNTI: 1+SFN_id>>2
#define RA_RNTI_LOW 0x0001 // SFN_id = 0
......@@ -287,7 +289,6 @@ typedef struct available_resource_UL_s{
typedef struct available_resource_DL_s{
uint32_t start_subframe;
uint32_t end_subframe;
uint32_t DLSF_num;
struct available_resource_DL_s *next, *prev;
}available_resource_DL_t;
......@@ -422,8 +423,6 @@ typedef struct schedule_result{
uint8_t *rar_buffer;
uint8_t *debug_str;
}schedule_result_t;
/*Flag structure used for trigger each scheduler*/
......
......@@ -18,6 +18,18 @@
#define flag_css_type2 0x2
#define flag_uss_v 0x4
#if 0 // disable now
#define flag_css_type1_ce0 0x1
#define flag_css_type1_ce1 0x2
#define flag_css_type1_ce2 0x4
#define flag_css_type2_ce0 0x8
#define flag_css_type2_ce1 0x10
#define flag_css_type2_ce2 0x20
#define flag_uss_v 0x40
#endif
// common
#define flag_mib 0x1
#define flag_sib1 0x2
......@@ -26,17 +38,19 @@
#define num_flags 2
int extend_space[num_flags] = {160, 160};
int extend_alpha_offset[num_flags] = {10, 10};
// type2 css, type1 css
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, int *scheduler_flags, int *common_flags){
//extern BCCH_DL_SCH_Message_NB_IoT_t SIB;
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 *max_subframe){
uint32_t subframe = abs_subframe % 10;
uint32_t frame = abs_subframe / 10;
int i;
uint32_t max = 0;
//NPRACH_Parameters_NB_IoT_r13_t **type2_css_info = SIB.message.choice.c1.choice.systemInformation_r13.criticalExtensions.choice.systemInformation_r13.sib_TypeAndInfo_r13.choice.sib2_r13.radioResourceConfigCommon_r13.nprach_Config_r13.nprach_ParametersList_r13.list.array;
if(subframe == 0){
*common_flags |= flag_mib;
}else if(subframe == 5){
......@@ -46,137 +60,124 @@ void eNB_scheduler_computing_flag_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t
}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);
/* uint32_t type2_css_pp[3] = { type2_css_info[0]->npdcch_NumRepetitions_RA_r13*type2_css_info[0]->npdcch_StartSF_CSS_RA_r13, type2_css_info[1]->npdcch_NumRepetitions_RA_r13*type2_css_info[1]->npdcch_StartSF_CSS_RA_r13, type2_css_info[2]->npdcch_NumRepetitions_RA_r13*type2_css_info[2]->npdcch_StartSF_CSS_RA_r13 };*/
uint32_t type2_css_pp[3] = {256, 256, 256};
uint32_t start_subframe;
for(i=0; i<1; ++i){ // only CE0
start_subframe = 0;
/*switch(type2_css_info[i]->npdcch_Offset_RA_r13){
case NPRACH_Parameters_NB_IoT_r13__npdcch_Offset_RA_r13_zero:
start_subframe = 0;
break;
case NPRACH_Parameters_NB_IoT_r13__npdcch_Offset_RA_r13_oneEighth:
start_subframe = type2_css_pp[i]>>3;
break;
case NPRACH_Parameters_NB_IoT_r13__npdcch_Offset_RA_r13_oneFourth:
start_subframe = type2_css_pp[i]>>2;
break;
case NPRACH_Parameters_NB_IoT_r13__npdcch_Offset_RA_r13_threeEighth:
start_subframe = (type2_css_pp[i]>>3)+(type2_css_pp[i]>>2);
break;
default: break;
}*/
if(((abs_subframe+1)%type2_css_pp[i])==start_subframe){
*scheduler_flags |= flag_css_type2;
max = MAX(max, extend_space[i]);
LOG_D(MAC,"[%d][computing flags] common searching space: %d, num subframe: %d\n", mac_inst->current_subframe, i, extend_space[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);
max = MAX(max, mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.T);
LOG_D(MAC,"[%d][computing flags] UE-spec searching space: %d, num subframe: %d\n", mac_inst->current_subframe, i, mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.T);
}
}
//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;
}
*/
*max_subframe = max;
}
/*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;
int a = 0;
int i;
uint8_t MIB_flag,SIB1_flag ;
uint32_t scheduler_flags, max_subframe, common_flags;
/*Check this subframe should schedule something, set the flag*/
scheduler_flags = 0;
common_flags = 0;
MIB_flag = 0;
SIB1_flag = 0;
uint32_t h,f,sf;
//int a;
printf("A\n");
//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];
}
}
}
printf("B\n");
int a;
eNB_scheduler_computing_flag_NB_IoT(mac_inst, abs_subframe, &scheduler_flags, &common_flags, &max_subframe);
if(scheduler_flags > 0){
extend_available_resource_DL(mac_inst, mac_inst->current_subframe + 1 + max_subframe);
extend_available_resource_DL(mac_inst, mac_inst->current_subframe +1 + max_subframe);
}
printf("C\n");
maintain_available_resource(mac_inst);
//static int test=2;
if((abs_subframe % rachperiod[4]) == rachstart[0]){
add_UL_Resource();
add_UL_Resource();
}
printf("D\n");
//Check if type2 searching space scheduling
if((scheduler_flags&flag_css_type2)>0){
schedule_RA_NB_IoT(mac_inst);
scheduler_flags &= ~(flag_css_type2);
}
printf("E\n");
//Check if type1 searching space scheduling
if((scheduler_flags&flag_css_type1)>0){
scheduler_flags &= ~(flag_css_type1);
}
//The scheduling time is current subframe + 1
convert_system_number(abs_subframe+1, &h, &f, &sf);
printf("F\n");
// 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();
LOG_D(MAC,"--------------[%04d][SchedulerUSS] Schedule USS list %d------------\n", mac_inst->current_subframe, (scheduler_flags&(flag_uss_v<<i))>>3);
schedule_uss_NB_IoT(0, mac_inst,sf, f, h, i);
LOG_D(MAC,"--------------[%04d][SchedulerUSS] Schedule USS list %d end------------\n", mac_inst->current_subframe, (scheduler_flags&(flag_uss_v<<i))>>3);
scheduler_flags &= ~(flag_uss_v<<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;
printf("G\n");
convert_system_number(abs_subframe, &h, &f, &sf);
a = output_handler(mac_inst, 0,0,h,f,sf,MIB_flag,SIB1_flag, abs_subframe);
a = output_handler(mac_inst, (module_id_t)0, 0, h, f, sf, MIB_flag, SIB1_flag, abs_subframe);
printf("Output_handler_return value : %d", a);
//DEBUG("--------------[%04d][eNB scheduler NB-IoT] End Scheduling------------\n", mac_inst->current_subframe);
if(a != 0){
LOG_D(MAC,"output handler error\n");
}
}
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;
// printf_FUNCTION_IN("[USS]");
//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;
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;
......@@ -192,45 +193,39 @@ void schedule_uss_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, u
//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_ID = mac_inst->UE_list_spec[index_ss].head;
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:
printf("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;
}
UE_template_temp = &(mac_inst->UE_list_spec[index_ss].UE_template_NB_IoT[UE_ID]);
LOG_D(MAC,"------Start Scheduling USS UE RNTI %d------\n", UE_template_temp->rnti);
if(UE_template_temp->RRC_connected!=1)
{
LOG_D(MAC,"[%04d][USS scheduler][UE%d] rrc not connected\n", mac_inst->current_subframe, UE_template_temp->rnti);
}
else
{
LOG_D(MAC,"[%04d][USS scheduler][UE%d] ", mac_inst->current_subframe, UE_template_temp->rnti);
switch(UE_template_temp->direction)
{
case 1: // Downlink Scheduling
LOG_D(MAC,"uss downlink scheduling.. \n");
schedule_DL_NB_IoT((module_id_t)0, mac_inst, UE_template_temp, hypersfn, frame, subframe);
break;
case 0: // Uplink Scheduling
LOG_D(MAC,"uss uplink scheduling.. \n");
schedule_UL_NB_IoT(mac_inst, UE_template_temp, subframe, frame, hypersfn);
break;
case -1: // Idle
LOG_D(MAC,"current idle.. \n");
default:
break;
}
}
UE_ID = UE_template_temp->next;
}
// printf_FUNCTION_OUT("[USS]");
}
......@@ -32,7 +32,7 @@ void init_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint8_t preamble_index, ce_le
RA_TEMPLATE_NB_IoT *migrate_node;
static int static_count=0;
printf("[%04d][RA scheduler][MSG1] RX %d\n", mac_inst->current_subframe, static_count++);
LOG_D(MAC,"[%04d][RA scheduler][MSG1] RX %d\n", mac_inst->current_subframe, static_count++);
for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
......@@ -43,7 +43,7 @@ void init_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint8_t preamble_index, ce_le
}
if(i==MAX_NUMBER_OF_UE_MAX_NB_IoT){
printf("[%04d][RA scheduler][MSG1] number of RA procedures is up to maximum..\n", mac_inst->current_subframe);
LOG_D(MAC,"[%04d][RA scheduler][MSG1] number of RA procedures is up to maximum..\n", mac_inst->current_subframe);
return ;
}
......@@ -54,7 +54,7 @@ void init_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint8_t preamble_index, ce_le
migrate_node->ta = ta;
migrate_node->next = (RA_TEMPLATE_NB_IoT *)0;
migrate_node->prev = (RA_TEMPLATE_NB_IoT *)0;
printf("[%04d][RA scheduler][MSG1][CE%d] Receive MSG1 RNTI %d preamble index %d\n", mac_inst->current_subframe, migrate_node->ce_level, migrate_node->ra_rnti, migrate_node->preamble_index);
LOG_D(MAC,"[%04d][RA scheduler][MSG1][CE%d] Receive MSG1 RNTI %d preamble index %d\n", mac_inst->current_subframe, migrate_node->ce_level, migrate_node->ra_rnti, migrate_node->preamble_index);
// insert to end of list
if((RA_TEMPLATE_NB_IoT *)0 == mac_inst->RA_msg2_list.head){
......@@ -68,196 +68,42 @@ void init_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint8_t preamble_index, ce_le
}
// 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;
//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);
// triggered time :
// 1) after tx rar, wait msg3 timeout
// 2) number of retransmit msg3 meet maximum or absent of ack/nack
// 3) number of retransmit msg4 meet maximum or absent of ack/nack
void cancel_ra(uint16_t rnti){
//uint32_t i;
}
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;
int rmax, fail, res, r;
int dci_subframe, dci_end_subframe, dci_first_subframe, num_dci_subframe;
int msg3_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;
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;
}
msg3_nodes = msg3_nodes->next;
}
return ;
return 0;
}
void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe){
// printf_FUNCTION_IN("schedule rar");
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;
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;
int msg3_subframe;//, msg3_end_subframe;
int dci_candidate, i, num_candidate;
int msg2_i_delay;
......@@ -266,14 +112,16 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
int rep=1;
sched_temp_UL_NB_IoT_t npusch_info;
int fail_num = 0;
int flag=0;
while((RA_TEMPLATE_NB_IoT *)0 != msg2_nodes){
if(flag==0)
flag=1;
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;
dci_subframe = abs_subframe;//mac_inst->current_subframe;
for(dci_candidate=0; dci_candidate<num_candidate; ++dci_candidate){
while(!is_dlsf(mac_inst, dci_subframe)){
++dci_subframe;
......@@ -297,7 +145,7 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
// 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_mcs = get_I_mcs(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];
......@@ -318,7 +166,7 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
}
// 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
......@@ -333,7 +181,8 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
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
msg3_subframe = msg2_end_subframe+msg3_scheduling_delay_table[msg3_scheduling_delay]+1;
if(0==Check_UL_resource(msg3_subframe, Nru*rep, &npusch_info, 1, 0)){ //1: multi-tones 0: single-tone. 1: format 2(ack/nack) 0: format 1
break;
}
}
......@@ -342,13 +191,13 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
}
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);
LOG_D(MAC,"[%04d][RA scheduler][MSG2] fail vector %d\n", abs_subframe, fail);
LOG_D(MAC,"[%04d][RA scheduler][MSG2][CE%d] rnti: %d preamble: %d fail vector %d\n", abs_subframe-1, msg2_nodes->ce_level, 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));
LOG_D(MAC,"[%04d][RA scheduler][MSG2][CE%d] rnti: %d preamble: %d scheduling success\n", abs_subframe-1, msg2_nodes->ce_level, msg2_nodes->ra_rnti, msg2_nodes->preamble_index);
dci_result = (schedule_result_t *)calloc(1, sizeof(schedule_result_t));
msg2_result = (schedule_result_t *)calloc(1, sizeof(schedule_result_t));
dci_n0 = (DCIFormatN0_t *)malloc(sizeof(DCIFormatN0_t));
dci_n1_rar = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t));
......@@ -379,8 +228,11 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
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];
//dci_result->printf_str = &str1[0];
//dci_result->dl_sdly = msg2_subframe - dci_end_subframe;
//dci_result->ul_sdly = msg3_subframe - msg2_end_subframe;
//dci_result->num_sf = msg2_end_subframe - msg2_subframe+1;
// for msg2
msg2_result->output_subframe = msg2_first_subframe;//msg2_subframe;
msg2_result->end_subframe = msg2_end_subframe;
......@@ -395,8 +247,10 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
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->printf_str = str2;
msg2_result->rar_buffer = msg2_nodes->rar_buffer;
//msg2_result->dl_sdly = -1;
//msg2_result->ul_sdly = -1;
// for msg3(fake DCI N0)
dci_n0->type = 0;
......@@ -411,8 +265,10 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
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);
LOG_D(MAC,"[%04d][RA scheduler][MSG2] RARDCI %d-%d RAR %d-%d MSG3 %d-%d\n", abs_subframe-1, dci_first_subframe, dci_end_subframe, msg2_first_subframe, msg2_end_subframe, npusch_info.sf_start, npusch_info.sf_end);
LOG_D(MAC,"[%04d][RA scheduler][MSG2][CE%d] Change RA-RNTI %d->T-CRNTI %d\n", abs_subframe-1, msg2_nodes->ce_level, msg2_nodes->ra_rnti, msg2_nodes->ue_rnti);
LOG_D(MAC,"[%04d][RA scheduler][MSG2][CE%d] RAR DCI %d-%d RAR %d-%d MSG3 %d-%d\n", abs_subframe-1, msg2_nodes->ce_level, 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
......@@ -459,15 +315,338 @@ void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
mac_inst->RA_msg3_list.tail = migrate_node;
}
}
//SCHEDULE_LOG("[%04d][RA scheduler][MSG2] failed number: %d\n", mac_inst->current_subframe, fail_num);
if(flag==1)
LOG_D(MAC,"[%04d][RA scheduler][MSG2] failed number: %d\n", abs_subframe-1, fail_num);
//printf_FUNCTION_OUT("schedule rar");
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){
void msg3_do_retransmit_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, rnti_t c_rnti){
RA_TEMPLATE_NB_IoT *msg3_nodes = mac_inst->RA_msg3_list.head;
//RA_TEMPLATE_NB_IoT *migrate_node;
if((RA_TEMPLATE_NB_IoT *)0 != msg3_nodes)
while((RA_TEMPLATE_NB_IoT *)0 != msg3_nodes){
if(msg3_nodes->ue_rnti == c_rnti){
msg3_nodes->wait_msg3_ack = 0;
msg3_nodes->msg3_retransmit_count++;
return ;
}
msg3_nodes = msg3_nodes->next;
}
return ;
}
void msg4_do_retransmit_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, rnti_t c_rnti){
RA_TEMPLATE_NB_IoT *msg4_nodes = mac_inst->RA_msg4_list.head;
//RA_TEMPLATE_NB_IoT *migrate_node;
if((RA_TEMPLATE_NB_IoT *)0 != msg4_nodes)
while((RA_TEMPLATE_NB_IoT *)0 != msg4_nodes){
if(msg4_nodes->ue_rnti == c_rnti){
msg4_nodes->wait_msg4_ack = 0;
msg4_nodes->msg4_retransmit_count++;
return ;
}
msg4_nodes = msg4_nodes->next;
}
return ;
}
void receive_msg3_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, rnti_t c_rnti, uint32_t phr, uint32_t ul_total_buffer){
// since successful receive msg3, tc-rnti become c-rnti.
RA_TEMPLATE_NB_IoT *msg3_nodes = mac_inst->RA_msg3_list.head;
RA_TEMPLATE_NB_IoT *migrate_node;
if((RA_TEMPLATE_NB_IoT *)0 != msg3_nodes)
while((RA_TEMPLATE_NB_IoT *)0 != msg3_nodes){
if(msg3_nodes->ue_rnti == c_rnti){
add_ue_NB_IoT(mac_inst, c_rnti, msg3_nodes->ce_level, phr, ul_total_buffer);// rnti, ce level
LOG_D(MAC,"[%04d][RA scheduler][MSG3][CE%d] Receive MSG3 T-CRNTI %d Preamble Index %d \n", mac_inst->current_subframe, msg3_nodes->ce_level, msg3_nodes->ue_rnti, msg3_nodes->preamble_index);
migrate_node = msg3_nodes;
// maintain list
if((RA_TEMPLATE_NB_IoT *)0 == migrate_node->prev){
// first node
mac_inst->RA_msg3_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_msg3_list.tail = migrate_node->prev; // including null
}else{
// not last node
migrate_node->next->prev = migrate_node->prev; // including null
}
RA_TEMPLATE_NB_IoT *msg4_nodes = mac_inst->RA_msg4_list.head;
// 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_msg4_list.head){
mac_inst->RA_msg4_list.head = migrate_node;
}else{
// not empty
mac_inst->RA_msg4_list.tail->next = migrate_node;
migrate_node->prev = mac_inst->RA_msg4_list.tail;
}
mac_inst->RA_msg4_list.tail = migrate_node;
return ;
}
msg3_nodes = msg3_nodes->next;
}
if((RA_TEMPLATE_NB_IoT *)0 == msg3_nodes){
LOG_D(MAC,"[%04d][RA scheduler][MSG3] receive msg3.. can't found the ue from crnti %x\n", mac_inst->current_subframe, c_rnti);
return;
}
}
void schedule_msg3_retransimission_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe){
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;
#if 0
// msg3 retransmission pre-processor
RA_TEMPLATE_NB_IoT *iterator, *iterator1;
while((RA_TEMPLATE_NB_IoT *)0 != msg3_nodes){
if(msg3_nodes->wait_msg3_ack == 0){
iterator = msg3_nodes;
while(iterator->prev != (RA_TEMPLATE_NB_IoT *)0 && iterator != mac_inst->RA_msg3_list.head){
if(iterator->prev->msg3_retransmit_count < iterator->msg3_retransmit_count){
//swap
iterator1 = iterator->prev;
if(iterator->prev == mac_inst->RA_msg3_list.head || iterator1->prev == (RA_TEMPLATE_NB_IoT *)0){
mac_inst->RA_msg3_list.head = iterator;
iterator1->prev = (RA_TEMPLATE_NB_IoT *)0; // b->prev
}else{
iterator->prev->prev->next = iterator; // a*->next
iterator->prev = iterator1->prev; // b->prev
}
if(iterator == mac_inst->RA_msg3_list.tail || iterator->next == (RA_TEMPLATE_NB_IoT *)0){
mac_inst->RA_msg3_list.tail = iterator1;
iterator1->next = (RA_TEMPLATE_NB_IoT *)0; // a->next
}else{
iterator->next->prev = iterator->prev; //b*->prev
iterator1->next = iterator->next; // a->next
}
iterator1->prev = iterator; // a->prev
iterator->next = iterator1; // b->next
}else{
break;
}
}
}
msg3_nodes = msg3_nodes->next;
}
#endif
msg3_nodes = mac_inst->RA_msg3_list.head;
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 = abs_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){
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
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){
msg3_subframe = 8+dci_end_subframe+msg3_scheduling_delay_table[msg3_scheduling_delay];
if(0==Check_UL_resource(msg3_subframe+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){
//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->printf_str = str6;
// dci_result->dl_sdly = msg3_subframe - dci_end_subframe + 1;
// dci_result->ul_sdly = -1;
//dci_result->num_sf = -1;
//dci_result->harq_round = msg3_nodes->msg3_retransmit_count;
//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);
LOG_D(MAC,"[%04d][RA scheduler][MSG3 re] MSG3DCI %d-%d MSG3 %d-%d\n", abs_subframe, dci_first_subframe, dci_end_subframe, npusch_info.sf_start, npusch_info.sf_end );
}else{
LOG_D(MAC,"[%04d][RA scheduler][MSG3 re] fail vector %d\n", abs_subframe, fail );
}
//++msg3_nodes->msg3_retransmit_count;
}
msg3_nodes = msg3_nodes->next;
}
return ;
}
void receive_msg4_ack_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, rnti_t rnti){
int i;
RA_TEMPLATE_NB_IoT *migrate_node = mac_inst->RA_msg4_list.head;
UE_TEMPLATE_NB_IoT *ue_info = (UE_TEMPLATE_NB_IoT *)0;
if((RA_TEMPLATE_NB_IoT *)0 != migrate_node)
while((RA_TEMPLATE_NB_IoT *)0 != migrate_node){
if(migrate_node->ue_rnti == rnti){
ue_info = mac_inst->UE_list_spec[(uint32_t)migrate_node->ce_level].UE_template_NB_IoT;
// maintain list
if((RA_TEMPLATE_NB_IoT *)0 == migrate_node->prev){
// first node
mac_inst->RA_msg4_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_msg4_list.tail = migrate_node->prev; // including null
}else{
// not last node
migrate_node->next->prev = migrate_node->prev; // including null
}
// release ra template
migrate_node->active = 0;
migrate_node->ce_level = 0;
migrate_node->msg3_retransmit_count = 0;
migrate_node->msg4_retransmit_count = 0;
migrate_node->next = (RA_TEMPLATE_NB_IoT *)0;
migrate_node->prev = (RA_TEMPLATE_NB_IoT *)0;
migrate_node->ta = 0;
migrate_node->preamble_index = 0;
migrate_node->ue_rnti = 0x0;
migrate_node->ra_rnti = 0x0;
migrate_node->wait_msg4_ack = 0;
migrate_node->wait_msg3_ack = 0;
break ;
}
migrate_node = migrate_node->next;
}
for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
if(ue_info[i].rnti == rnti){
if(ue_info[i].ul_total_buffer>0)
{
ue_info[i].direction = 0;
}
else
{
ue_info[i].direction = 1;
}
ue_info[i].RRC_connected = 1;
LOG_D(MAC,"[%04d][RA scheduler][MSG4] received UE:%d direction: %d \n", mac_inst->current_subframe, rnti, ue_info[i].direction );
break;
}
}
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, int abs_subframe){
//printf_FUNCTION_IN("[SCHEDULER RA MSG4]");
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;
......@@ -483,28 +662,66 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
schedule_result_t *msg4_result;
schedule_result_t *harq_result;
#if 0
// msg4 pre-processor
RA_TEMPLATE_NB_IoT *iterator, *iterator1;
while((RA_TEMPLATE_NB_IoT *)0 != msg4_nodes){
if(msg4_nodes->wait_msg4_ack == 0){
iterator = msg4_nodes;
while(iterator->prev != (RA_TEMPLATE_NB_IoT *)0 && iterator != mac_inst->RA_msg4_list.head){
if(iterator->prev->msg4_retransmit_count < iterator->msg4_retransmit_count){
//swap
iterator1 = iterator->prev;
if(iterator->prev == mac_inst->RA_msg4_list.head || iterator1->prev == (RA_TEMPLATE_NB_IoT *)0){
mac_inst->RA_msg4_list.head = iterator;
iterator1->prev = (RA_TEMPLATE_NB_IoT *)0; // b->prev
}else{
iterator->prev->prev->next = iterator; // a*->next
iterator->prev = iterator1->prev; // b->prev
}
if(iterator == mac_inst->RA_msg4_list.tail || iterator->next == (RA_TEMPLATE_NB_IoT *)0){
mac_inst->RA_msg4_list.tail = iterator1;
iterator1->next = (RA_TEMPLATE_NB_IoT *)0; // a->next
}else{
iterator->next->prev = iterator->prev; //b*->prev
iterator1->next = iterator->next; // a->next
}
iterator1->prev = iterator; // a->prev
iterator->next = iterator1; // b->next
}else{
break;
}
}
}
msg4_nodes = msg4_nodes->next;
}
#endif
msg4_node = (available_resource_DL_t *)0;
//print_available_resource_DL();
msg4_nodes = mac_inst->RA_msg4_list.head;
while((RA_TEMPLATE_NB_IoT *)0 != msg4_nodes){
if(msg4_nodes->wait_msg4_ack == 0){
fail=0;
//printf_FUNCTION_IN("[SCHEDULER RA MSG4 DCI]");
// 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;
dci_subframe = abs_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);
LOG_D(MAC,"%d msg4 dci %d - %d\n", abs_subframe, dci_first_subframe, dci_end_subframe);
break;
}
res = num_dci_subframe;
......@@ -519,7 +736,9 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
//failed
fail|=1;
}
//printf_FUNCTION_OUT("[SCHEDULER RA MSG4 DCI]");
//printf_FUNCTION_IN("[SCHEDULER RA MSG4 PAYLOAD]");
// check msg4 resource
rep = dl_rep[msg4_nodes->ce_level];
num_msg4_subframe = 1*rep; // 8 subframes
......@@ -529,8 +748,7 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
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);
LOG_D(MAC,"%d msg4 %d - %d\n", abs_subframe, msg4_first_subframe, msg4_end_subframe);
break;
}
}
......@@ -538,9 +756,10 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
//failed
fail|=2;
}
//printf_FUNCTION_OUT("[SCHEDULER RA MSG4 PAYLOAD]");
//printf_FUNCTION_IN("[SCHEDULER RA MSG4 HARQ]");
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){
......@@ -553,10 +772,10 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
if(4 == HARQ_delay){
fail |= 4;
}
//printf_FUNCTION_OUT("[SCHEDULER RA MSG4 HARQ]");
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);
LOG_D(MAC,"[%04d][RA scheduler][MSG4][CE%d] rnti: %d scheduling success\n", abs_subframe-1, msg4_nodes->ce_level, msg4_nodes->ue_rnti);
msg4_nodes->wait_msg4_ack = 1;
DCIFormatN1_t *dci_n1_msg4 = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t));
// dci entity
......@@ -584,6 +803,10 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
dci_result->R_harq = 0;
dci_result->next = (schedule_result_t *)0;
dci_result->DCI_pdu = (void *)dci_n1_msg4;
//dci_result->dl_sdly = msg4_subframe - dci_end_subframe;
//dci_result->ul_sdly = harq_subframe - msg4_end_subframe;
//dci_result->num_sf = msg4_end_subframe - msg4_subframe+1;
//dci_result->harq_round = msg4_nodes->msg4_retransmit_count;
// for msg4
msg4_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
......@@ -599,7 +822,7 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
msg4_result->R_harq = 0;
msg4_result->next = (schedule_result_t *)0;
msg4_result->DCI_pdu = (void *)dci_n1_msg4;
//msg4_result->harq_round = msg4_nodes->msg4_retransmit_count;
harq_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
harq_result->rnti = msg4_nodes->ue_rnti;
......@@ -614,22 +837,22 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
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;
/*if(msg4_nodes->msg4_retransmit_count==0){
dci_result->printf_str = str3;
msg4_result->printf_str = str4;
harq_result->printf_str = str5;
}else{
dci_result->debug_str = str8;
msg4_result->debug_str = str9;
harq_result->debug_str = str10;
}
dci_result->printf_str = str8;
msg4_result->printf_str = str9;
harq_result->printf_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);
LOG_D(MAC,"[%04d][RA scheduler][MSG4] UE:%x MSG4DCI %d-%d MSG4 %d-%d HARQ %d-%d\n", abs_subframe-1, msg4_nodes->ue_rnti, dci_first_subframe, dci_end_subframe, msg4_first_subframe, msg4_end_subframe, HARQ_info.sf_start, HARQ_info.sf_end);
LOG_D(MAC,"[%04d][RA scheduler][MSG4][CE%d] MSG4 DCI %d-%d MSG4 %d-%d HARQ %d-%d\n", abs_subframe-1, msg4_nodes->ce_level, 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);
......@@ -638,7 +861,6 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
// 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
......@@ -649,31 +871,80 @@ void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
}
}
}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);
}
LOG_D(MAC,"[%04d][RA scheduler][MSG4] fail vector %d\n", abs_subframe, fail );
LOG_D(MAC,"[%04d][RA scheduler][MSG4] rnti: %d preamble: %d fail vector %d\n", abs_subframe-1, msg4_nodes->ra_rnti, msg4_nodes->preamble_index, fail);
}
}
msg4_nodes = msg4_nodes->next;
}
//printf_FUNCTION_OUT("[SCHEDULER RA MSG4]");
return ;
}
void schedule_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
//uint32_t current_subframe = mac_inst->current_subframe;
//printf_FUNCTION_IN("[SCHEDULER RA]");
uint32_t schedule_subframe = mac_inst->current_subframe + 1;
schedule_subframe = schedule_subframe % 1048576; // 20 bits, 10 bits + 10 bits
schedule_msg3_retransimission_NB_IoT(mac_inst);
schedule_rar_NB_IoT(mac_inst);
schedule_msg4_NB_IoT(mac_inst);
// this is the priority order in current stage.
schedule_msg3_retransimission_NB_IoT(mac_inst, schedule_subframe);
schedule_rar_NB_IoT(mac_inst, schedule_subframe);
schedule_msg4_NB_IoT(mac_inst, schedule_subframe);
//printf_FUNCTION_OUT("[SCHEDULER RA]");
return ;
}
// 7bytes TODO: CHECK
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);
}
......@@ -12,31 +12,55 @@
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
unsigned char str[6][7] = { "SIBs_1", "SIBs_2", "SIBs_3", "SIBs_4", "SIBs_5", "SIBs_6" };
unsigned char si_repetition_pattern_table[4] = { 20, 40, 80, 160};
void schedule_sibs_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, int start_subframe1){
char str[6][7] = { "SIBs_1", "SIBs_2", "SIBs_3", "SIBs_4", "SIBs_5", "SIBs_6" };
#define num_flags 2
extern int extend_space[num_flags];
extern int extend_alpha_offset[num_flags];
void schedule_sibs(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, int start_subframe1){
available_resource_DL_t *pt[8] = { (available_resource_DL_t *)0 };
uint32_t first_subframe[8] = { -1 };
int first_subframe[8] = { -1 };
//uint32_t end_subframe[8] = { -1 };
schedule_result_t *new_node;
DCIFormatN1_t *sibs_dci;
uint32_t j, i, k, num_subframe, last_subframe, residual_subframe;
uint32_t j, i, k;
int residual_subframe, num_subframe, last_subframe;
num_subframe = mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_tb;
for(k=0, i=start_subframe1;i<(start_subframe1+mac_inst->rrc_config.si_window_length);i+=si_repetition_pattern_table[mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_repetition_pattern], ++k){
//printf("[debug][sibs%d] subframe: %d, check %d", sibs_order, i, num_subframe);
pt[k] = (available_resource_DL_t *)check_sibs_resource(mac_inst, i, i+9, num_subframe, &residual_subframe, &last_subframe, &first_subframe[k]);
int rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[0].mac_npdcch_NumRepetitions_RA_NB_IoT;
rmax = (rmax * 10) >> 3; // x1.25
for(k=0, i=start_subframe1; i<(start_subframe1+mac_inst->rrc_config.si_window_length); i+=si_repetition_pattern[mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_repetition_pattern], ++k){
LOG_D(MAC,"[debug][sibs%d] subframe: %d, check %d", sibs_order, i, num_subframe);
LOG_D(MAC,"[%d][%d][%d] [%d][%d]\n", i, start_subframe1, mac_inst->rrc_config.si_window_length, sibs_order, si_repetition_pattern[mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_repetition_pattern]);
//system("pause");
#if 0 //disable new feature
// avoid to occupied others searching space. TODO: css, uss connect with configuration module
// start start+rmax
// i i+9
int continue_flag=0;
for(l=0; l<num_flags; ++l){
if((extend_space[l]>>extend_alpha_offset[l] <= i%extend_space[l] && ((extend_space[l]>>extend_alpha_offset[l])+rmax) >= i%extend_space[l]) ||
(extend_space[l]>>extend_alpha_offset[l] <= (i+9)%extend_space[l] && ((extend_space[l]>>extend_alpha_offset[l])+rmax) >= (i+9)%extend_space[l])){
continue_flag = 1;
}
}
if(continue_flag == 1)
continue;
#endif
pt[k] = (available_resource_DL_t *)check_sibs_resource(mac_inst, i, i+9, num_subframe, &residual_subframe, &last_subframe, &first_subframe[k]);
num_subframe = residual_subframe;
//printf("-- rest: %d, last: %d start: %d\n", num_subframe, last_subframe, start_subframe1);
LOG_D(MAC,"-- rest: %d, last: %d start: %d\n", num_subframe, last_subframe, start_subframe1);
if(0==residual_subframe){
if(0==residual_subframe){LOG_D(MAC,"output\n\n");
sibs_dci = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t));
sibs_dci->type = 1;
sibs_dci->orderIndicator = 0;
......@@ -48,8 +72,8 @@ void schedule_sibs_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, in
sibs_dci->HARQackRes = 0;
sibs_dci->DCIRep = 0;
for(k=0, j=start_subframe1;j<=i;++k, j+=si_repetition_pattern_table[mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_repetition_pattern]){
for(k=0, j=start_subframe1;j<=i;++k, j+=si_repetition_pattern[mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_repetition_pattern]){
LOG_D(MAC,"for1 k=%d j=%d i=%d rep=%d\n", k, j, i, si_repetition_pattern[mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_repetition_pattern]);
if((available_resource_DL_t *)0 != pt[k]){
new_node = (schedule_result_t *)malloc(sizeof(schedule_result_t));
// fill new node
......@@ -65,11 +89,14 @@ void schedule_sibs_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, in
new_node->R_harq = 0; // useless
new_node->next = (schedule_result_t *)0;
new_node->DCI_pdu = (void *)sibs_dci;
new_node->debug_str = str[sibs_order];
//new_node->debug_str = str[sibs_order];
LOG_D(MAC,"for*1 %d %d %d %p\n", pt[k]->start_subframe, first_subframe[k], (j==i)?last_subframe:j+9, new_node);
fill_resource_DL(mac_inst, pt[k], first_subframe[k], (j==i)?last_subframe:j+9, new_node);
LOG_D(MAC,"for*2\n");
}
LOG_D(MAC,"for2\n");
}
return ;
}
}
......
......@@ -12,6 +12,7 @@
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
/*DL scheduler*/
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
......@@ -25,7 +26,7 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
//DCI N1
DCIFormatN1_t *DCI_N1 = (DCIFormatN1_t*)malloc(sizeof(DCIFormatN1_t));
//RLC Status
//mac_rlc_status_resp_NB_IoT_t rlc_status;
//mac_rlc_status_resp_t rlc_status;
/*Index in DCI_N1*/
uint32_t I_mcs, I_tbs, I_delay, I_sf;
/*value for corresponding index*/
......@@ -42,20 +43,22 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
//uint32_t mac_sdu_size;
//uint8_t sdu_temp[SCH_PAYLOAD_SIZE_MAX_NB_IoT];
logical_chan_id_t logical_channel;
//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_mcs = get_I_mcs(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);
LOG_D(MAC,"[%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 0
if(UE_info->HARQ_round==0)
{
//Get RLC status
......@@ -72,7 +75,14 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
0);
data_size = rlc_status.bytes_in_buffer;
*/
data_size = 200;
//data_size = 200;
data_size=0;
int ue_index;
for(ue_index=0;ue_index<UE_NUM_SIM;++ue_index)
{
if(UE_info_sim[ue_index].tc_rnti==UE_info->rnti)
data_size = UE_info_sim[ue_index].data_size;
}
}
/*Retransmission*/
else
......@@ -81,15 +91,19 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
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);
LOG_D(MAC,"[%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);
#endif
data_size=200; //for testing
LOG_D(MAC,"[%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);
LOG_D(MAC,"[%04d][DLSchedulerUSS][Fail] No data in DCCH0_NB_IoT\n", mac_inst->current_subframe);
return;
}
if(data_size>127)
......@@ -99,15 +113,16 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
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);
LOG_D(MAC,"[%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);
LOG_D(MAC,"[%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);
//LOG_D(MAC,"[%04d][DLSchedulerUSS][%d] Search_space_start_sf %d Search_space_end_sf %d\n", mac_inst->current_subframe, UE_info->rnti, mac_inst->current_subframe, convert_system_number_sf(hyperSF_start, frame_start, subframe_start), 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);
//LOG_D(MAC,"[%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);
......@@ -115,20 +130,20 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
/*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);
//LOG_D(MAC,"[%04d][DLSchedulerUSS] Candidate num %d allocate success\n", cdd_num);
//LOG_D(MAC,"[%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);
LOG_D(MAC,"[%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);
//LOG_D(MAC,"[%04d][DLSchedulerUSS] Number SF %d index SF %d\n", n_sf, I_sf);
//LOG_D(MAC,"[%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)
......@@ -140,15 +155,15 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
/*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);
//LOG_D(MAC,"[%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));
//LOG_D(MAC,"[%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) );
//LOG_D(MAC,"[%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);
//LOG_D(MAC,"[%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)
......@@ -170,46 +185,48 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
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;
//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);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d][Success] Complete scheduling with data size %d\n", mac_inst->current_subframe, UE_info->rnti, data_size);
//LOG_D(MAC,"[%04d][DLSchedulerUSS] RNTI %d\n", mac_inst->current_subframe, UE_info->rnti);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d][Success] Allocate NPDCCH subframe %d to subframe %d candidate index %d\n", mac_inst->current_subframe, UE_info->rnti, NPDCCH_info->sf_start, NPDCCH_info->sf_end, cdd_num);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d][Success] Scheduling delay index: %d value: %d + 4\n", mac_inst->current_subframe, UE_info->rnti, I_delay, get_scheduling_delay(I_delay, UE_info->R_max));
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d][Success] Allocate NPDSCH subframe %d to subframe %d\n", mac_inst->current_subframe, UE_info->rnti, NPDSCH_info->sf_start, NPDSCH_info->sf_end);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d][Success] Allocate HARQ feedback subframe %d to subframe %d\n", mac_inst->current_subframe, UE_info->rnti, HARQ_info->sf_start, HARQ_info->sf_end);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d] Allocate NPDCCH subframe %d to subframe %d candidate index %d\n", mac_inst->current_subframe, UE_info->rnti, NPDCCH_info->sf_start, NPDCCH_info->sf_end, cdd_num);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d] Scheduling delay index: %d value: %d + 4\n", mac_inst->current_subframe, UE_info->rnti, I_delay, get_scheduling_delay(I_delay, UE_info->R_max));
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d] Allocate NPDSCH subframe %d to subframe %d\n", mac_inst->current_subframe, UE_info->rnti, NPDSCH_info->sf_start, NPDSCH_info->sf_end);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d] Allocate HARQ feedback subframe %d to subframe %d\n", mac_inst->current_subframe, UE_info->rnti, 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);
//LOG_D(MAC,"[%04d][DLSchedulerUSS] HARQ index %d\n", HARQ_info->ACK_NACK_resource_field);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d] 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, UE_info->rnti, 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");
//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);
generate_scheduling_result_DL(NPDCCH_info, NPDSCH_info, HARQ_info, DCI_N1, UE_info->rnti, TBS, UE_info->DLSCH_pdu.payload);
//LOG_D(MAC,"[%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;
//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);
LOG_D(MAC,"[%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);
LOG_D(MAC,"[%04d][DLSchedulerUSS] Complete DL scheduling\n", mac_inst->current_subframe);
//Change the UE state to idle
UE_info->direction = -1;
//SCHEDULE_LOG("[%04d][DLSchedulerUSS] RNTI %d complete scheduling\n", mac_inst->current_subframe, UE_info->rnti);
//LOG_D(MAC,"[%04d][DLSchedulerUSS] RNTI %d complete scheduling\n", mac_inst->current_subframe, UE_info->rnti);
return;
}
......@@ -217,33 +234,34 @@ void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE
/*harq resource fail*/
if(end_flagHARQ==-1)
{
//DEBUG("[%04d][DLSchedulerUSS] [Fail]HARQ_delay %d HARQ Resource fail\n", mac_inst->current_subframe, HARQ_delay);
//LOG_D(MAC,"[%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);
//LOG_D(MAC,"[%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);
//LOG_D(MAC,"[%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);
//LOG_D(MAC,"[%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);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d][Fail] Resource allocate fail\n", mac_inst->current_subframe, UE_info->rnti);
LOG_D(MAC,"[%04d][DLSchedulerUSS][%d][Fail] 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);
//LOG_D(MAC,"[%04d][check_resource_NPDCCH_NB_IoT] NPDCCH sf start %d\n", mac_inst->current_subframe, NPDCCH_info->sf_start);
//LOG_D(MAC,"[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);
}
......@@ -271,7 +289,7 @@ int check_resource_DL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_sta
/*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);
//LOG_D(MAC,"abs_end = %d\n", schedule_info->sf_end);
rsc_start_sf = schedule_info->sf_start;
if(schedule_info->sf_start<=schedule_info->sf_end)
{
......@@ -282,15 +300,15 @@ int check_resource_DL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_sta
/*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");
//LOG_D(MAC,"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);
//LOG_D(MAC,"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");
//LOG_D(MAC,"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)
{
......@@ -301,14 +319,14 @@ int check_resource_DL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_sta
/*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);
//LOG_D(MAC,"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");
//LOG_D(MAC,"check_resource_DL_NB_IoT flag 3\n");
return -1;
}
......@@ -327,7 +345,7 @@ uint32_t generate_dlsch_header_NB_IoT(uint8_t *pdu, uint32_t num_sdu, logical_ch
for(i=0;i<num_sdu;++i)
{
printf("index %d sdu size %d\n", i, sdu_length[i]);
LOG_D(MAC,"index %d sdu size %d\n", i, sdu_length[i]);
if(sdu_length[i]>127)
{
num_sdu_L_15++;
......@@ -342,11 +360,11 @@ uint32_t generate_dlsch_header_NB_IoT(uint8_t *pdu, uint32_t num_sdu, logical_ch
padding_size = TBS-total_sdu_size-num_ce;
if(padding_size<0)
{
printf("[ERROR]TBS less than require subheader and control element\n");
LOG_D(MAC,"[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);
LOG_D(MAC,"total SDU size %d\n", total_sdu_size);
LOG_D(MAC,"padding size %d\n", padding_size);
if(padding_size>2)
{
flag_end_padding=1;
......@@ -388,7 +406,7 @@ uint32_t generate_dlsch_header_NB_IoT(uint8_t *pdu, uint32_t num_sdu, logical_ch
mac_header->F2=0;
mac_header->R=0;
offset++;
printf("last sdu\n");
LOG_D(MAC,"last sdu\n");
}
else
{
......@@ -430,7 +448,6 @@ uint32_t generate_dlsch_header_NB_IoT(uint8_t *pdu, uint32_t num_sdu, logical_ch
}
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;
......@@ -444,7 +461,7 @@ void fill_DCI_N1(DCIFormatN1_t *DCI_N1, UE_TEMPLATE_NB_IoT *UE_info, uint32_t sc
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)
void generate_scheduling_result_DL(sched_temp_DL_NB_IoT_t* DCI_info, sched_temp_DL_NB_IoT_t* NPDSCH_info, sched_temp_UL_NB_IoT_t* HARQ_info, DCIFormatN1_t *DCI_inst, 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));
......@@ -454,40 +471,51 @@ void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subfra
schedule_result_t *tmp, *tmp1;
/*fill NPDCCH result*/
NPDCCH_result->rnti=rnti;
NPDCCH_result->output_subframe = DCI_subframe;
NPDCCH_result->output_subframe = DCI_info->sf_start;
NPDCCH_result->end_subframe = DCI_info->sf_end;
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_pdu = DCI;
NPDCCH_result->DCI_release = 0;
NPDCCH_result->channel = NPDCCH;
// NPDCCH_result->printf_str = dl_str1;
NPDCCH_result->next = NULL;
/*fill NPDSCH result*/
NPDSCH_result->rnti=rnti;
NPDSCH_result->output_subframe = NPDSCH_subframe;
//NPDSCH_result->output_subframe = NPDSCH_subframe;
NPDSCH_result->output_subframe = NPDSCH_info->sf_start;
NPDSCH_result->end_subframe = NPDSCH_info->sf_end;
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_pdu = DCI;
NPDSCH_result->DCI_release = 0;
NPDSCH_result->channel = NPDSCH;
//NPDSCH_result->printf_str = dl_str2;
NPDSCH_result->next = NULL;
/*fill HARQ result*/
HARQ_result->rnti=rnti;
HARQ_result->output_subframe = HARQ_subframe;
//HARQ_result->output_subframe = HARQ_subframe;
HARQ_result->output_subframe = HARQ_info->sf_start;
HARQ_result->end_subframe = HARQ_info->sf_end;
HARQ_result->sdu_length = 0;
HARQ_result->direction = 1;
HARQ_result->direction = 0;
HARQ_result->rnti_type = 3;
HARQ_result->DLSCH_pdu = NULL;
HARQ_result->DCI_pdu = DCI_pdu;
HARQ_result->DCI_pdu = DCI;
HARQ_result->DCI_release = 1;
HARQ_result->channel = NPUSCH;
HARQ_result->npusch_format = 1;
// HARQ_result->printf_str = dl_str3;
HARQ_result->next = NULL;
//DEBUG("[generate_scheduling_result_DL] Generate NPDCCH node\n");
//LOG_D(MAC,"[generate_scheduling_result_DL] Generate NPDCCH node\n");
/*NPDCCH scheduling result*/
// be the first node of the DL scheduling result
......@@ -498,20 +526,20 @@ void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subfra
{
//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");
LOG_D(MAC,"[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)
if(DCI_info->sf_start < 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);
//LOG_D(MAC,"[generate_scheduling_result_DL] node output subframe %d at NPDCCH part\n", tmp->output_subframe);
}
/*tail*/
if(tmp==NULL)
......@@ -531,17 +559,17 @@ void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subfra
}
}
}
//DEBUG("[generate_scheduling_result_DL] Generate NPDCSH node\n");
//LOG_D(MAC,"[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)
if(NPDSCH_info->sf_start < tmp->output_subframe)
{
break;
}
//DEBUG("[generate_scheduling_result_DL] node output subframe %d at NPDSCH part\n", tmp->output_subframe);
//LOG_D(MAC,"[generate_scheduling_result_DL] node output subframe %d at NPDSCH part\n", tmp->output_subframe);
tmp1 = tmp;
tmp = tmp->next;
}
......@@ -561,7 +589,7 @@ void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subfra
schedule_result_list_DL = NPDSCH_result;
}
}
//DEBUG("[generate_scheduling_result_DL] Generate HARQ node\n");
//LOG_D(MAC,"[generate_scheduling_result_DL] Generate HARQ node\n");
/*HARQ scheduling result*/
// be the first node of UL
// be the first node of UL
......@@ -577,12 +605,13 @@ void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subfra
tmp = schedule_result_list_UL;
while(tmp!=NULL)
{
if(HARQ_subframe < tmp->output_subframe)
if(HARQ_info->sf_start < tmp->output_subframe)
{
break;
}
//DEBUG("[generate_scheduling_result_DL] node output subframe %d at HARQ part\n", tmp->output_subframe);
//LOG_D(MAC,"[generate_scheduling_result_DL] node output subframe %d at HARQ part\n", tmp->output_subframe);
tmp1 = tmp;
tmp = tmp->next;
}
if(tmp==NULL)
......@@ -602,16 +631,15 @@ void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subfra
}
}
/*
DEBUG("---[generate_scheduling_result_DL] schedule result after generate---\n");
LOG_D(MAC,"---[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);
LOG_D(MAC,"[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;
......@@ -619,7 +647,7 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
int align_left;
int align_right;
uint32_t H_temp, f_temp, sf_temp;
uint32_t H_temp_r, f_temp_r, sf_temp_r;
uint32_t H_temp_r, f_temp_r, sf_temp_r;
if(NPDSCH_info==NULL)
{
......@@ -632,12 +660,23 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
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);
//LOG_D(MAC,"[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
// divided into two nodes, insert after oritinal node.
// A | node | B
// A | node | temp | B
temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
if((available_resource_DL_t *)0 == NPDCCH_info->node->next){
available_resource_DL_last = temp;
}else{
NPDCCH_info->node->next->prev = temp;
}
temp->next = NPDCCH_info->node->next;
temp->prev = NPDCCH_info->node;
NPDCCH_info->node->next = temp;
......@@ -657,21 +696,27 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
{
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;
}
}
// process next node element.
if(NPDCCH_info->node->prev==NULL){
// first node of list
available_resource_DL = NPDCCH_info->node->next;
}else{
NPDCCH_info->node->prev->next = NPDCCH_info->node->next;
}
// process prev node element.
if(NPDCCH_info->node->next!=NULL){
NPDCCH_info->node->next->prev = NPDCCH_info->node->prev;
}else{
// end node of list
available_resource_DL_last = NPDCCH_info->node->prev;
}
free(NPDCCH_info->node);
break;
default:
......@@ -685,7 +730,7 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
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);
LOG_D(MAC,"[%04d][maintain_resource_DL] NPDCCH and NPDSCH using the same node\n", mac_inst->current_subframe);
}
/****Maintain NPDCCH node*******/
// divided into two node
......@@ -696,17 +741,21 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
//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);
//LOG_D(MAC,"[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
// divided into two nodes, insert after oritinal node.
// A | node | B
// A | node | temp | B
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;
}
}else{
NPDCCH_info->node->next->prev = temp;
}
temp->next = NPDCCH_info->node->next;
temp->prev = NPDCCH_info->node;
......@@ -726,7 +775,7 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
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);
LOG_D(MAC,"[%04d][maintain_resource_DL] NPDCCH keep one node\n", mac_inst->current_subframe);
}
else
{
......@@ -735,25 +784,27 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
break;
case 2:
// delete
printf("[%04d][maintain_resource_DL] NPDCCH delete node\n", mac_inst->current_subframe);
LOG_D(MAC,"[%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;
}
// 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;
}
}
// process next node element.
if(NPDCCH_info->node->prev==NULL){
// first node of list
available_resource_DL = NPDCCH_info->node->next;
}else{
NPDCCH_info->node->prev->next = NPDCCH_info->node->next;
}
// process prev node element.
if(NPDCCH_info->node->next!=NULL){
NPDCCH_info->node->next->prev = NPDCCH_info->node->prev;
}else{
// end node of list
available_resource_DL_last = NPDCCH_info->node->prev;
}
free(NPDCCH_info->node);
break;
default:
......@@ -766,13 +817,17 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
switch(align_left+align_right)
{
case 0:
// divided into two node
// divided into two nodes, insert after oritinal node.
// A | node | B
// A | node | temp | B
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;
}
}else{
NPDSCH_info->node->next->prev = temp;
}
temp->next = NPDSCH_info->node->next;
temp->prev = NPDSCH_info->node;
......@@ -798,23 +853,21 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
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;
}
}
if(NPDSCH_info->node->prev==NULL){
// first node of list
available_resource_DL = NPDSCH_info->node->next;
}else{
NPDSCH_info->node->prev->next = NPDSCH_info->node->next;
}
// process prev node element.
if(NPDSCH_info->node->next!=NULL){
NPDSCH_info->node->next->prev = NPDSCH_info->node->prev;
}else{
// end node of list
available_resource_DL_last = NPDSCH_info->node->prev;
}
free(NPDSCH_info->node);
break;
default:
......@@ -824,6 +877,81 @@ void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t
free(NPDCCH_info);
free(NPDSCH_info);
}
}
/*Get MCS index*/
uint32_t get_I_mcs(int CE_level)
{
if(CE_level==0)
{
return 13;
}
else if(CE_level==1)
{
return 8;
}
else
{
return 2;
}
}
uint32_t get_max_tbs(uint32_t I_tbs)
{
return MAC_TBStable_NB_IoT[I_tbs][7]/8;
}
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))
{
//LOG_D(MAC,"[get_tbs]TBS %d SF index %d\n", 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;
}
}
LOG_D(MAC,"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;
}
}
/*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;
}
}
uint8_t get_index_Rep_dl(uint16_t R)
......@@ -838,7 +966,7 @@ uint8_t get_index_Rep_dl(uint16_t R)
return i;
}
}
printf("[get_index_Rep] error\n");
LOG_D(MAC,"[get_index_Rep] error\n");
}
return -1;
}
\ No newline at end of file
return 0;
}
......@@ -12,7 +12,6 @@
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
unsigned char str20[] = "DCI_uss";
unsigned char str21[] = "DATA_uss";
......@@ -31,6 +30,12 @@ int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info
int Iru = 0, Nru, I_rep,N_rep,total_ru;
int dly = 0,uplink_time = 0;
if(UE_info->ul_total_buffer<=0)
{
LOG_D(MAC,"[%04d][UL scheduler][UE:%05d] No UL data in buffer\n", mac_inst->current_subframe, UE_info->rnti);
return -1;
}
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));
......@@ -57,14 +62,14 @@ int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info
//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);
//LOG_D(MAC,"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);
TBS=get_TBS_UL_NB_IoT(mcs,UE_info->multi_tone,Iru);
}*/
mcs = mapped_mcs[UE_info->CE_level][mappedMcsIndex];
......@@ -75,7 +80,7 @@ int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info
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);
//LOG_D(MAC,"TBS : %d UL_buffer: %d\n", TBS, UE_info->ul_total_buffer);
Nru = RU_table[Iru];
DL_end = NPDCCH_info->sf_end;
......@@ -83,7 +88,7 @@ int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info
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);
LOG_D(MAC,"[%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
......@@ -104,14 +109,17 @@ int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info
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);
LOG_D(MAC,"[%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);
LOG_D(MAC,"[%04d][ULSchedulerUSS][%d][Success] complete scheduling with data size %d\n", mac_inst->current_subframe, UE_info->rnti, UE_info->ul_total_buffer);
LOG_D(MAC,"[%04d][ULSchedulerUSS][%d][Success] 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);
//Change the UE state to idle
UE_info->direction = -1;
return 0;
}
}
......@@ -120,299 +128,86 @@ int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info
/*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);
LOG_D(MAC,"[%04d][ULSchedulerUSS][%d][Fail] UL scheduling USS fail\n", mac_inst->current_subframe, UE_info->rnti);
LOG_D(MAC,"[%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)
void rx_sdu_NB_IoT(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t subframe, uint16_t rnti, uint8_t *sdu, uint16_t length)
{
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;
}
unsigned char rx_ces[5], num_ce = 0, num_sdu = 0, *payload_ptr, i; // MAX Control element
unsigned char rx_lcids[5];//for NB_IoT-IoT, NB_IoT_RB_MAX should be fixed to 5 (2 DRB+ 3SRB)
unsigned short rx_lengths[5];
//int UE_id = 0;
int BSR_index=0;
int DVI_index = 0;
int PHR = 0;
int ul_total_buffer = 0;
//mac_NB_IoT_t *mac_inst;
UE_TEMPLATE_NB_IoT *UE_info;
//DEBUG("[UL scheduler][singletone]no proper resource for this allocation\n");
return -1;
//mac_inst = get_mac_inst(module_id);
}
// note: if lcid < 25 this is sdu, otherwise this is CE
payload_ptr = parse_ulsch_header_NB_IoT(sdu, &num_ce, &num_sdu,rx_ces, rx_lcids, rx_lengths, length);
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;
}
//LOG_D(MAC,"num_CE= %d, num_sdu= %d, rx_ces[0] = %d, rx_lcids = %d, rx_lengths[0] = %d, length = %d\n",num_ce,num_sdu,rx_ces[0],rx_lcids[0],rx_lengths[0],length);
/*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)
for (i = 0; i < num_ce; i++)
{
switch(rx_ces[i])
{
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;
}
case CRNTI:
// find UE id again, confirm the UE, intial some ue specific parameters
payload_ptr+=2;
break;
case SHORT_BSR:
// update BSR here
UE_info = get_ue_from_rnti(mac_inst, rnti);
BSR_index = payload_ptr[0] & 0x3f;
UE_info->ul_total_buffer = BSR_table[BSR_index];
payload_ptr+=1;
break;
default:
LOG_D(MAC,"Received unknown MAC header (0x%02x)\n", rx_ces[i]);
break;
}
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 result =-1;
if(fmt2_flag ==0)
for (i = 0; i < num_sdu; i++)
{
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)
switch(rx_lcids[i])
{
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");
case CCCH_NB_IoT:
// MSG3 content: |R|R|PHR|PHR|DVI|DVI|DVI|DVI|CCCH payload
PHR = ((payload_ptr[0] >> 5) & 0x01)*2+((payload_ptr[0]>>4) & 0x01);
DVI_index = (payload_ptr[0] >>3 & 0x01)*8+ (payload_ptr[0] >>2 & 0x01)*4 + (payload_ptr[0] >>1 & 0x01)*2 +(payload_ptr[0] >>0 & 0x01);
//LOG_D(MAC,"DVI_index= %d\n",DVI_index);
ul_total_buffer = DV_table[DVI_index];
LOG_D(MAC,"PHR = %d, ul_total_buffer = %d\n",PHR,ul_total_buffer);
// go to payload
payload_ptr+=1;
rx_lengths[i]-=1;
LOG_D(MAC,"rx_lengths : %d\n", rx_lengths[i]);
//NB_IoT_mac_rrc_data_ind(payload_ptr,mac_inst,rnti);
//NB_IoT_receive_msg3(mac_inst,rnti,PHR,ul_total_buffer);
break;
case DCCH0_NB_IoT:
case DCCH1_NB_IoT:
// UE specific here
//NB_IoT_mac_rlc_data_ind(payload_ptr,mac_inst,rnti);
break;
// all the DRBS
case DTCH0_NB_IoT:
default:
//NB_IoT_mac_rlc_data_ind(payload_ptr,mac_inst,rnti);
break;
}
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;
}
}
payload_ptr+=rx_lengths[i];
}
}
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);
}
uint8_t *parse_ulsch_header_NB_IoT( uint8_t *mac_header,
......@@ -483,80 +278,3 @@ uint16_t length, ce_len=0;
return(mac_header_ptr);
}
void rx_sdu_NB_IoT(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t subframe, uint16_t rnti, uint8_t *sdu, uint16_t length)
{
unsigned char rx_ces[5], num_ce = 0, num_sdu = 0, *payload_ptr, i; // MAX Control element
unsigned char rx_lcids[5];//for NB_IoT-IoT, NB_IoT_RB_MAX should be fixed to 5 (2 DRB+ 3SRB)
unsigned short rx_lengths[5];
//int UE_id = 0;
int BSR_index=0;
int DVI_index = 0;
int PHR = 0;
int ul_total_buffer = 0;
//mac_NB_IoT_t *mac_inst;
UE_TEMPLATE_NB_IoT *UE_info;
//mac_inst = get_mac_inst(module_id);
// note: if lcid < 25 this is sdu, otherwise this is CE
payload_ptr = parse_ulsch_header_NB_IoT(sdu, &num_ce, &num_sdu,rx_ces, rx_lcids, rx_lengths, length);
//printf("num_CE= %d, num_sdu= %d, rx_ces[0] = %d, rx_lcids = %d, rx_lengths[0] = %d, length = %d\n",num_ce,num_sdu,rx_ces[0],rx_lcids[0],rx_lengths[0],length);
for (i = 0; i < num_ce; i++)
{
switch(rx_ces[i])
{
case CRNTI:
// find UE id again, confirm the UE, intial some ue specific parameters
payload_ptr+=2;
break;
case SHORT_BSR:
// update BSR here
UE_info = get_ue_from_rnti(mac_inst, rnti);
BSR_index = payload_ptr[0] & 0x3f;
UE_info->ul_total_buffer = BSR_table[BSR_index];
payload_ptr+=1;
break;
default:
printf("Received unknown MAC header (0x%02x)\n", rx_ces[i]);
break;
}
}
for (i = 0; i < num_sdu; i++)
{
switch(rx_lcids[i])
{
case CCCH_NB_IoT:
// MSG3 content: |R|R|PHR|PHR|DVI|DVI|DVI|DVI|CCCH payload
PHR = ((payload_ptr[0] >> 5) & 0x01)*2+((payload_ptr[0]>>4) & 0x01);
DVI_index = (payload_ptr[0] >>3 & 0x01)*8+ (payload_ptr[0] >>2 & 0x01)*4 + (payload_ptr[0] >>1 & 0x01)*2 +(payload_ptr[0] >>0 & 0x01);
//printf("DVI_index= %d\n",DVI_index);
ul_total_buffer = DV_table[DVI_index];
printf("PHR = %d, ul_total_buffer = %d\n",PHR,ul_total_buffer);
// go to payload
payload_ptr+=1;
rx_lengths[i]-=1;
printf("rx_lengths : %d\n", rx_lengths[i]);
//NB_IoT_mac_rrc_data_ind(payload_ptr,mac_inst,rnti);
//NB_IoT_receive_msg3(mac_inst,rnti,PHR,ul_total_buffer);
break;
case DCCH0_NB_IoT:
case DCCH1_NB_IoT:
// UE specific here
//NB_IoT_mac_rlc_data_ind(payload_ptr,mac_inst,rnti);
break;
// all the DRBS
case DTCH0_NB_IoT:
default:
//NB_IoT_mac_rlc_data_ind(payload_ptr,mac_inst,rnti);
break;
}
payload_ptr+=rx_lengths[i];
}
}
\ No newline at end of file
......@@ -11,7 +11,6 @@
#ifndef __MAC_EXTERN_NB_IOT_H__
#define __MAC_EXTERN_NB_IOT_H__
// #ifdef USER_MODE
// //#include "stdio.h"
// #endif //USER_MODE
......@@ -27,26 +26,10 @@
//#include "LAYER2/MAC/vars_NB_IoT.h"
//NB-IoT
//extern IF_Module_NB_IoT_t *if_inst_NB_IoT;
//extern eNB_MAC_INST_NB_IoT *mac_inst_NB_IoT;
extern eNB_MAC_INST_NB_IoT *mac_inst;
// //extern uint32_t EBSR_Level[63];
// extern const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE];
// //extern uint32_t Extended_BSR_TABLE[63]; ----currently not used
// extern const uint8_t cqi2fmt0_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE];
// extern const uint8_t cqi2fmt1x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE];
// extern const uint8_t cqi2fmt2x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE];
// extern UE_MAC_INST *UE_mac_inst;
// extern eNB_MAC_INST *eNB_mac_inst;
// extern eNB_RRC_INST *eNB_rrc_inst;
//extern UE_RRC_INST_NB_IoT *UE_rrc_inst_NB_IoT;
// extern UE_MAC_INST *ue_mac_inst;
// extern MAC_RLC_XFACE *Mac_rlc_xface;
// extern uint8_t Is_rrc_registered;
//#ifndef USER_MODE
......@@ -126,8 +109,10 @@ extern const int dl_rep[3];
extern const uint32_t dci_rep[3];
extern const uint32_t harq_rep[3];
//SIBs
extern int extend_space[2];
extern int extend_alpha_offset[2];
extern const int si_repetition_pattern[4];
#endif //DEF_H
......@@ -56,8 +56,7 @@ void init_mac_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst)
mac_inst->sib1_flag[i] = 0;
mac_inst->sib1_count[i] = 0;
}
//rrc_mac_config_req_NB_IoT(&mac_inst->rrc_config, 1, 1, 0, 0);
//rrc_mac_config_req_NB_IoT(&mac_inst->rrc_config, 1, 1, 0, 0);
init_tool_sib1(mac_inst);
// output handler
......@@ -70,7 +69,7 @@ void init_mac_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst)
mac_inst->RA_msg4_list.tail = (RA_TEMPLATE_NB_IoT *)0;
sib1_NB_IoT_sched_t *config = &mac_inst->rrc_config.sib1_NB_IoT_sched_config;
// DLSF Table
init_dlsf_info(mac_inst, &DLSF_information);
......@@ -86,13 +85,13 @@ void init_mac_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst)
}
mac_inst->sib1_count[i]=j;
}
//printf("%d", mac_inst->sib1_period);
//LOG_D(MAC,"%d", mac_inst->sib1_period);
for(i=0, j=0;i<640;++i){
//printf("*%d", i);
//LOG_D(MAC,"*%d", i);
if(is_dlsf(mac_inst, i)){
++j;
}
//printf("-");
//LOG_D(MAC,"-");
if(i%10==9){
mac_inst->dlsf_table[i/10] = j;
}
......
......@@ -15,7 +15,7 @@
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)
{
//if(schedule_result_list_UL != (schedule_result_t *)0){
// printf("time %d\n", mac_inst->current_subframe);
// LOG_D(MAC,"time %d\n", mac_inst->current_subframe);
// print_schedule_result_DL(); print_schedule_result_UL(); getchar();
//}
......@@ -23,7 +23,7 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
uint8_t MIB_size = 0;
uint8_t SIB1_size = 0, i = 0;
Sched_Rsp_NB_IoT_t *SCHED_info = &(mac_inst->Sched_INFO);
Sched_Rsp_NB_IoT_t *SCHED_info = (Sched_Rsp_NB_IoT_t*) malloc(sizeof(Sched_Rsp_NB_IoT_t));
nfapi_dl_config_request_pdu_t *dl_config_pdu;
nfapi_hi_dci0_request_pdu_t* hi_dci0_pdu;
nfapi_ul_config_request_pdu_t* ul_config_pdu = NULL;
......@@ -46,13 +46,13 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)malloc(sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu = SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list;
//printf("first DL node output: %d current: %d\n",schedule_result_list_DL->output_subframe,current_time);
//LOG_D(MAC,"first DL node output: %d current: %d\n",schedule_result_list_DL->output_subframe,current_time);
//printf("test current: %d\n",current_time);
//LOG_D(MAC,"test current: %d\n",current_time);
if(MIB_flag == 1)
{
//printf("[%d]MIB\n",current_time);
//LOG_D(MAC,"[%d]MIB\n",current_time);
//MIB_size = mac_rrc_data_req_eNB_NB_IoT(*MIB)
SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_NBCH_PDU_TYPE;
......@@ -63,7 +63,7 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
// fill MIB PDU
//SCHED_info->TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->NB_IoTch_pdu.NB_IoTch_pdu_rel13.pdu_index].segments[0].segment_data = MIB;
LOG_I(MAC,"NB-IoT fill MIB\n");
LOG_D(MAC,"NB-IoT fill MIB\n");
//dl_scheduled(mac_inst->current_subframe, _NPBCH, 0, "MIB");
}
else if(SIB1_flag == 1)
......@@ -79,7 +79,7 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.modulation = 2;
//SCHED_info->TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index].segments[0].segment_data = SIB1;
LOG_I(MAC,"NB-IoT fill SIB1\n");
LOG_D(MAC,"NB-IoT fill SIB1\n");
//start symbol, Resource assignment, Repetition number, Number of subframe Resource assignment lost for now
//dl_scheduled(mac_inst->current_subframe, _NPDSCH, SI_RNTI, "SIB1");
}
......@@ -87,24 +87,24 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
else if(schedule_result_list_DL==NULL)
{
DL_empty = 1;
//printf("no remaining node of DL scheduling result\n");
//LOG_D(MAC,"no remaining node of DL scheduling result\n");
}else
{
if(schedule_result_list_DL->output_subframe < current_time)
{
while(schedule_result_list_DL->output_subframe < current_time)
{
//printf("This error if there is DL scheduling result node before the current time\n");
//LOG_D(MAC,"This error if there is DL scheduling result node before the current time\n");
tmp = schedule_result_list_DL;
schedule_result_list_DL = schedule_result_list_DL->next;
free(tmp);
//printf("test2 current: %d\n",current_time);
//LOG_D(MAC,"test2 current: %d\n",current_time);
//break;
if(schedule_result_list_DL == NULL){
return -1;
}
}
//printf("return\n");
//LOG_D(MAC,"return\n");
//return -1;
}
else if (schedule_result_list_DL->output_subframe == current_time)
......@@ -115,8 +115,8 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
if(schedule_result_list_DL->direction == DL)
{
LOG_I(MAC,"NB-IoT fill DL_DCI\n");
//printf("Sched Info DL DCI here\n");
LOG_D(MAC,"NB-IoT fill DL_DCI\n");
//LOG_D(MAC,"Sched Info DL DCI here\n");
SCHED_info->DL_req->dl_config_request_body.number_dci = 1;
DCI_pdu = schedule_result_list_DL->DCI_pdu;
// not consider the case transmitting 2 DCIs for the moment also not consider N2 now
......@@ -139,7 +139,7 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number = ((DCIFormatN1_t *)DCI_pdu)->DCIRep;
}else if(schedule_result_list_DL->direction == UL)
{
LOG_I(MAC,"NB-IoT fill DL_DCI\n");
LOG_D(MAC,"NB-IoT fill DL_DCI\n");
SCHED_info->HI_DCI0_req = (nfapi_hi_dci0_request_t*)malloc(sizeof(nfapi_hi_dci0_request_t));
SCHED_info->HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)malloc(sizeof(nfapi_hi_dci0_request_pdu_t));
hi_dci0_pdu = SCHED_info->HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list;
......@@ -161,7 +161,7 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
}
break;
case NPDSCH:
LOG_I(MAC,"NB-IoT fill DL Data\n");
LOG_D(MAC,"NB-IoT fill DL Data\n");
DCI_pdu = schedule_result_list_DL-> DCI_pdu;
SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE;
......@@ -187,30 +187,30 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
schedule_result_list_DL = schedule_result_list_DL->next;
//printf("subframe check scheduling result next %d\n",schedule_result_list_DL->output_subframe);
//LOG_D(MAC,"subframe check scheduling result next %d\n",schedule_result_list_DL->output_subframe);
}
}
//printf("There is no downlink transmission\n");
//LOG_D(MAC,"There is no downlink transmission\n");
if(schedule_result_list_UL==NULL)
{
UL_empty = 1;
//printf("no remaining node of UL scheduling result\n");
//LOG_D(MAC,"no remaining node of UL scheduling result\n");
}else
{
if(schedule_result_list_UL->output_subframe < current_time)
{
while(schedule_result_list_UL->output_subframe < current_time)
{
//printf("This error if there is UL scheduling result node before the current time\n");
//LOG_D(MAC,"This error if there is UL scheduling result node before the current time\n");
tmp = schedule_result_list_UL;
schedule_result_list_UL = schedule_result_list_UL->next;
free(tmp);
return -1;
}
//printf("return\n");
//LOG_D(MAC,"return\n");
//return -1;
}
else if(schedule_result_list_UL->output_subframe == current_time)
......@@ -224,8 +224,8 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
{
if(schedule_result_list_UL->channel == NPUSCH)
{
//printf("first UL \n");
LOG_I(MAC,"NB-IoT fill ul_config_pdu\n");
//LOG_D(MAC,"first UL \n");
LOG_D(MAC,"NB-IoT fill ul_config_pdu\n");
SCHED_info->UL_req->ul_config_request_body.number_of_pdus ++;
//SCHED_info->UL_req.sfn_sf = ;
(ul_config_pdu + i) ->pdu_type = NFAPI_UL_CONFIG_NULSCH_PDU_TYPE;
......@@ -237,7 +237,7 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
// bug here
(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.nulsch_format = 0;
(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size = UL_TBS_Table[((DCIFormatN0_t *)DCI_pdu)->mcs][((DCIFormatN0_t *)DCI_pdu)->ResAssign];
//printf("test\n");
//LOG_D(MAC,"test\n");
(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.rnti = schedule_result_list_UL->rnti;
(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.subcarrier_indication = ((DCIFormatN0_t *)DCI_pdu)->scind;
(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.resource_assignment = ((DCIFormatN0_t *)DCI_pdu)->ResAssign;
......@@ -270,21 +270,21 @@ int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_
if(schedule_result_list_UL == NULL)
break;
}else{
printf("error\n");
LOG_D(MAC,"error\n");
}
}
}
if(DL_empty == 1 )
{
//printf("[hypersfn:%2d][frame:%2d][subframe:%2d]No remaining DL result\n",hypersfn,frame,subframe);
//LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]No remaining DL result\n",hypersfn,frame,subframe);
}
if(UL_empty == 1)
{
//printf("[hypersfn:%2d][frame:%2d][subframe:%2d]no remaining UL result\n",hypersfn,frame,subframe);
//LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]no remaining UL result\n",hypersfn,frame,subframe);
}
//printf("[hypersfn:%2d][frame:%2d][subframe:%2d]filling the schedule response successfully\n",hypersfn,frame,subframe);
//LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]filling the schedule response successfully\n",hypersfn,frame,subframe);
return 0;
}
......@@ -41,70 +41,7 @@
void mac_top_init_eNB_NB_IoT(void);
int l2_init_eNB_NB_IoT(void);
// main schedule functions
void eNB_scheduler_computing_flag_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe, int *scheduler_flags, int *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_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint8_t preamble_index, ce_level_t ce_level, uint32_t sfn_id, uint16_t ta);
void init_tool_sib1(eNB_MAC_INST_NB_IoT *mac_inst);
void init_dlsf_info(eNB_MAC_INST_NB_IoT *mac_inst, DLSF_INFO_t *DLSF_info);
void init_mac_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
int is_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe);
void init_dl_list(eNB_MAC_INST_NB_IoT *mac_inst);
void setting_nprach(void);
void init_rrc_NB_IoT(void);
void add_UL_Resource_node(available_resource_UL_t **head, uint32_t *end_subframe, uint32_t ce_level);
void add_UL_Resource(void);
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);
uint32_t to_earfcn_NB_IoT(int eutra_bandP,uint32_t dl_CarrierFreq, float m_dl);
uint32_t from_earfcn_NB_IoT(int eutra_bandP,uint32_t dl_earfcn, float m_dl);
int32_t get_uldl_offset_NB_IoT(int eutra_band);
void config_mib_fapi_NB_IoT(
int physCellId,
......@@ -136,90 +73,148 @@ void rrc_mac_config_req_NB_IoT(
uint8_t ded_flag,
uint8_t ue_list_ded_num);
// 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, uint32_t check_start_subframe, uint32_t check_end_subframe, uint32_t num_subframe, uint32_t *residual_subframe, uint32_t *out_last_subframe, uint32_t *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);
///system
void init_mac_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
//void init_rrc_NB_IoT();
void release_mac_inst(uint8_t order);
eNB_MAC_INST_NB_IoT *get_mac_inst(uint8_t order);
uint8_t register_mac_inst(eNB_MAC_INST_NB_IoT *inst, uint8_t order);
///tool
void init_tool(sib1_NB_IoT_sched_t *config);
void UE_info_setting(UE_TEMPLATE_NB_IoT *UE_info);
UE_TEMPLATE_NB_IoT *get_ue_from_rnti(eNB_MAC_INST_NB_IoT *inst, rnti_t rnti);
///scheduler
void eNB_dlsch_ulsch_scheduler_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe);
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 *max_subframe);
//Calvin temp define self-tools
int init_debug(eNB_MAC_INST_NB_IoT *inst);
void maintain_available_resource(eNB_MAC_INST_NB_IoT *mac_inst);
void extend_available_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int max_subframe);
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);
void init(eNB_MAC_INST_NB_IoT *mac_inst);
void init_dl_list(eNB_MAC_INST_NB_IoT *mac_inst);
int is_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe);
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_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int check_subframe, int num_subframes, int *out_last_subframe, int *out_first_subframe);
void print_available_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst);
void print_schedule_result_DL(void);
void print_schedule_result_UL(void);
void add_ue_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint16_t rnti, ce_level_t ce, uint32_t PHR, uint32_t ul_total_buffer);
void remove_ue(eNB_MAC_INST_NB_IoT *mac_inst, uint16_t rnti, ce_level_t ce);
// SIBs
void schedule_sibs(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, int start_subframe);
//RA
void msg3_do_retransmit_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, rnti_t c_rnti);
void msg4_do_retransmit_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, rnti_t c_rnti);
void schedule_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
void init_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint8_t preamble_index, ce_level_t ce_level, uint32_t sfn_id, uint16_t ta);
void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe);
void receive_msg3_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, rnti_t c_rnti, uint32_t phr, uint32_t ul_total_buffer);
void schedule_msg3_retransimission_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe);
void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe);
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);
void receive_msg4_ack_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, rnti_t rnti);
int multi_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info);
//USS
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);
//DATA
uint8_t *parse_ulsch_header( uint8_t *mac_header,
uint8_t *num_ce,
uint8_t *num_sdu,
uint8_t *rx_ces,
uint8_t *rx_lcids,
uint16_t *rx_lengths,
uint16_t tb_length );
/*******UL Scheduler**********/
void print_scheduling_result_UL(void);
void print_available_UL_resource(void);
/*set nprach configuration at intial time*/
void setting_nprach(void);
/*Uplink main scheduler*/
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);
/*Check available uplink resource list, if there is available uplink resource, return 0, otherwise, return 1*/
int Check_UL_resource(uint32_t DL_end, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int multi_tone, int fmt2_flag);
/*Get I Repetition number in DCI*/
int get_I_REP(int N_rep);
/*Get N REP from preamble repeat*/
int get_N_REP(int CE_level);
/*Get TBS from mcs, multi-tone, Iru*/
int get_TBS_UL_NB_IoT(uint32_t mcs,uint32_t multi_tone,int Iru);
/*get I tbs from mcs and multi-tone*/
int get_I_TBS_NB_IoT(int x,int y);
/*Get DCI REP from R max and R*/
int get_DCI_REP(uint32_t R,uint32_t R_max);
/*Check single tone resource list*/
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);
/*Check multi tone resource list*/
int multi_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info);
/*Generate scheduling result of DCI N0 and Uplink config*/
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_inst, rnti_t rnti, uint8_t *ul_debug_str, uint8_t *dl_debug_str);
/*Adjust UL resource by removing the used resource*/
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_pdu, 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);
/*Initialize resource by nprach configuration*/
void Initialize_Resource(void);
/*Function to extend uplink resource grid*/
//void add_UL_Resource(eNB_MAC_INST_NB_IoT *mac_inst);
void add_UL_Resource(void);
/*Get ACK/NAK resource field*/
int get_resource_field_value(int subcarrier, int k0);
/*Get DL Repetition index*/
uint8_t get_index_Rep_dl(uint16_t R);
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);
/*******DL Scheduler********/
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 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);
uint32_t get_I_mcs(int CE_level);
uint32_t get_max_tbs(uint32_t I_tbs);
uint32_t get_tbs(uint32_t data_size, uint32_t I_tbs, uint32_t *I_sf);
uint32_t get_num_sf(uint32_t I_sf);
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);
//void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subframe, uint32_t HARQ_subframe, DCIFormatN1_t *DCI, rnti_t rnti, uint32_t TBS, uint8_t *DLSCH_pdu);
void generate_scheduling_result_DL(sched_temp_DL_NB_IoT_t* DCI_info, sched_temp_DL_NB_IoT_t* NPDSCH_info, sched_temp_UL_NB_IoT_t* HARQ_info, DCIFormatN1_t *DCI_inst, rnti_t rnti, uint32_t TBS, uint8_t *DLSCH_pdu);
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);
//Transfrom source into hyperSF, Frame, Subframe format
void convert_system_number(uint32_t source_sf,uint32_t *hyperSF, uint32_t *frame, uint32_t *subframe);
//Trnasform hyperSF, Frame, Subframe format into subframe unit
uint32_t convert_system_number_sf(uint32_t hyperSF, uint32_t frame, uint32_t 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);
void init_dlsf_info(eNB_MAC_INST_NB_IoT *mac_inst, DLSF_INFO_t *DLSF_info);
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);
void init_tool_sib1(eNB_MAC_INST_NB_IoT *mac_inst);
//int is_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe);
/**DL test , delete**/
available_resource_DL_t* new_dl_node(uint32_t start_subframe, uint32_t end_subframe, uint32_t dlsf);
void initialize_dl_resource(available_resource_DL_t *DL_Resource_node, uint32_t start_subframe, uint32_t end_subframe, uint32_t dlsf);
void insert_dl_resource(available_resource_DL_t *DL_Resource_node);
void insert_schedule_result(schedule_result_t **list, int subframe, schedule_result_t *node);
//interface with IF
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);
UE_TEMPLATE_NB_IoT *get_ue_from_rnti(eNB_MAC_INST_NB_IoT *inst, rnti_t rnti);
//debug function
uint8_t *parse_ulsch_header_NB_IoT( uint8_t *mac_header, uint8_t *num_ce, uint8_t *num_sdu, uint8_t *rx_ces, uint8_t *rx_lcids, uint16_t *rx_lengths, uint16_t tb_length);
void print_available_resource_DL(void);
void rx_sdu_NB_IoT(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t subframe, uint16_t rnti, uint8_t *sdu, uint16_t length);
void print_available_UL_resource(void);
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);
// main
//interface with IF
uint32_t to_earfcn_NB_IoT(int eutra_bandP,uint32_t dl_CarrierFreq, float m_dl);
uint8_t *parse_ulsch_header_NB_IoT( uint8_t *mac_header, uint8_t *num_ce, uint8_t *num_sdu, uint8_t *rx_ces, uint8_t *rx_lcids, uint16_t *rx_lengths, uint16_t tb_length);
uint32_t from_earfcn_NB_IoT(int eutra_bandP,uint32_t dl_earfcn, float m_dl);
void rx_sdu_NB_IoT(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t subframe, uint16_t rnti, uint8_t *sdu, uint16_t length);
int32_t get_uldl_offset_NB_IoT(int eutra_band);
#endif
......@@ -12,84 +12,92 @@
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
void init_tool_sib1(eNB_MAC_INST_NB_IoT *mac_inst){
int i, j;
void print_available_UL_resource(void){
//int repetition_pattern = 1;// 1:every2frame, 2:every4frame, 3:every8frame, 4:every16frame
for(i=0;i<8;++i){
mac_inst->sib1_flag[(i<<1)+mac_inst->rrc_config.sib1_NB_IoT_sched_config.starting_rf] = 1;
}
int sixtone_num=0;
int threetone_num=0;
int singletone1_num=0;
int singletone2_num=0;
int singletone3_num=0;
for(i=0, j=0;i<64;++i){
if(mac_inst->sib1_flag[i]==1){
++j;
}
mac_inst->sib1_count[i]=j;
}
available_resource_UL_t *available_resource;
mac_inst->sib1_period = 256 / mac_inst->rrc_config.sib1_NB_IoT_sched_config.repetitions;
///sixtone
available_resource = available_resource_UL->sixtone_Head;
return ;
}
while(available_resource!=NULL)
{
sixtone_num++;
LOG_D(MAC,"[sixtone][Node %d] start %d , end %d\n",sixtone_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
void init_dlsf_info(eNB_MAC_INST_NB_IoT *mac_inst, DLSF_INFO_t *DLSF_info)
{
uint16_t dlsf_num_temp=0;
uint16_t i;
uint16_t j=0;
///threetone
available_resource = available_resource_UL->threetone_Head;
DLSF_info->sf_to_dlsf_table=(uint16_t*)malloc(mac_inst->sib1_period*10*sizeof(uint16_t));
for(i=0;i<mac_inst->sib1_period*10;++i)
{
if(is_dlsf(mac_inst, i)==1)
while(available_resource!=NULL)
{
dlsf_num_temp++;
DLSF_info->sf_to_dlsf_table[i]=dlsf_num_temp;
threetone_num++;
LOG_D(MAC,"[threetone][Node %d] start %d, end %d\n",threetone_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
else
///singletone1
available_resource = available_resource_UL->singletone1_Head;
while(available_resource!=NULL)
{
DLSF_info->sf_to_dlsf_table[i]=dlsf_num_temp;
singletone1_num++;
LOG_D(MAC,"[singletone1][Node %d] start %d, end %d\n",singletone1_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
}
DLSF_info->num_dlsf_per_period = dlsf_num_temp;
DLSF_info->dlsf_to_sf_table = (uint16_t*)malloc(dlsf_num_temp*sizeof(uint16_t));
for(i=0;i<mac_inst->sib1_period*10;++i)
{
if(is_dlsf(mac_inst, i)==1)
///singletone1
available_resource = available_resource_UL->singletone2_Head;
while(available_resource!=NULL)
{
DLSF_info->dlsf_to_sf_table[j]= i;
j++;
singletone2_num++;
LOG_D(MAC,"[singletone2][Node %d] start %d, end %d\n",singletone2_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
}
}
int is_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe){
int frame = abs_subframe/10;
int subframe = abs_subframe%10;
///singletone1
available_resource = available_resource_UL->singletone3_Head;
while(available_resource!=NULL)
{
singletone3_num++;
LOG_D(MAC,"[singletone3][Node %d] start %d, end %d\n",singletone3_num,available_resource->start_subframe,available_resource->end_subframe);
available_resource = available_resource->next;
}
return !(subframe==0||subframe==5||((frame&0x1)==0&&subframe==9)||(mac_inst->sib1_flag[frame%mac_inst->sib1_period]==1&&subframe==4));
}
void init_dl_list(eNB_MAC_INST_NB_IoT *mac_inst){
available_resource_DL_t *node;
void print_scheduling_result_UL(void)
{
schedule_result_t *scheduling_result_tmp;
node = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
node->next = (available_resource_DL_t *)0;
node->prev = (available_resource_DL_t *)0;
scheduling_result_tmp = schedule_result_list_DL;
available_resource_DL = node;
available_resource_DL_last = node;
while(scheduling_result_tmp!=NULL)
{
LOG_D(MAC,"[UE:%05d][%s] output subframe : %d\n", scheduling_result_tmp->rnti, ((scheduling_result_tmp->channel==NPDCCH)? "NPDCCH":"NPDSCH"), scheduling_result_tmp->output_subframe);
scheduling_result_tmp = scheduling_result_tmp->next;
}
node->start_subframe = 0;
node->end_subframe = mac_inst->rrc_config.si_window_length;
node->DLSF_num = calculate_DLSF(mac_inst, node->start_subframe, node->end_subframe);
mac_inst->schedule_subframe_DL = mac_inst->rrc_config.si_window_length;
scheduling_result_tmp = schedule_result_list_UL;
while(scheduling_result_tmp!=NULL)
{
LOG_D(MAC,"[UE:%05d][NPUSCH] output subframe : %d\n", scheduling_result_tmp->rnti, scheduling_result_tmp->output_subframe);
scheduling_result_tmp = scheduling_result_tmp->next;
}
// init sibs for first si-window
schedule_sibs_NB_IoT(mac_inst, 0, 0);
}
void setting_nprach(void){
void setting_nprach(){
nprach_list[0].nprach_Periodicity = rachperiod[4];
nprach_list[0].nprach_StartTime = rachstart[0];
......@@ -112,11 +120,81 @@ void setting_nprach(void){
// fixed nprach configuration
}
void Initialize_Resource_node(available_resource_UL_t *tone_head, available_resource_UL_t *npusch_frame, int tone)
{
int i=0;
available_resource_UL_t *second_node;
second_node = (available_resource_UL_t*)malloc(sizeof(available_resource_UL_t));
if(tone == sixtone)
i=2;
else if(tone == threetone)
i=1;
else
i=0;
tone_head->start_subframe = ceil ( (nprach_list+i)->nprach_StartTime + 1.4*4*((nprach_list+i)->numRepetitionsPerPreambleAttempt) ) ;
tone_head->end_subframe = (nprach_list+i)->nprach_StartTime-1 + (nprach_list+i)->nprach_Periodicity;
second_node->start_subframe = tone_head->start_subframe + (nprach_list+i)->nprach_Periodicity;
second_node->end_subframe = tone_head->end_subframe + (nprach_list+i)->nprach_Periodicity;
second_node->next =NULL;
tone_head->next = second_node;
*npusch_frame = *tone_head->next;
////////////////////////CALVIN TIMING DIAGRAM GENERATOR///////////////////////////
#ifdef TIMING_GENERATOR
uint32_t ii, jj;
for(ii=(nprach_list+i)->nprach_StartTime; ii<tone_head->start_subframe; ++ii){
if(ii == sim_end_time) break;
for(jj=0; jj<(nprach_list+i)->nprach_NumSubcarriers; ++jj){
ul_scheduled(ii, 0, (nprach_list+i)->nprach_SubcarrierOffset + jj, _NPRACH, 0, (char *)0);
}
}
for(ii=tone_head->end_subframe+1; ii<second_node->start_subframe; ++ii){
if(ii == sim_end_time) break;
for(jj=0; jj<(nprach_list+i)->nprach_NumSubcarriers; ++jj){
ul_scheduled(ii, 0, (nprach_list+i)->nprach_SubcarrierOffset + jj, _NPRACH, 0, (char *)0);
}
}
#endif
////////////////////////CALVIN TIMING DIAGRAM GENERATOR///////////////////////////
}
/*when there is SIB-2 configuration coming to MAC, filled the uplink resource grid*/
void Initialize_Resource(void){
///memory allocate to Head
available_resource_UL = (available_resource_tones_UL_t*)malloc(sizeof(available_resource_tones_UL_t));
available_resource_UL->sixtone_Head = (available_resource_UL_t *)0;
available_resource_UL->threetone_Head = (available_resource_UL_t *)0;
available_resource_UL->singletone1_Head = (available_resource_UL_t *)0;
available_resource_UL->singletone2_Head = (available_resource_UL_t *)0;
available_resource_UL->singletone3_Head = (available_resource_UL_t *)0;
available_resource_UL->sixtone_end_subframe = 0;
available_resource_UL->threetone_end_subframe = 0;
available_resource_UL->singletone1_end_subframe = 0;
available_resource_UL->singletone2_end_subframe = 0;
available_resource_UL->singletone3_end_subframe = 0;
add_UL_Resource();
add_UL_Resource();
LOG_D(MAC,"Initialization of the UL Resource grid has been done\n");
}
void add_UL_Resource_node(available_resource_UL_t **head, uint32_t *end_subframe, uint32_t ce_level){
available_resource_UL_t *new_node, *iterator;
new_node = (available_resource_UL_t *)malloc(sizeof(available_resource_UL_t));
new_node->next = (available_resource_UL_t *)0;
new_node->prev = (available_resource_UL_t *)0;
new_node->start_subframe = *end_subframe + ceil( (nprach_list+ce_level)->nprach_StartTime + 1.4*4*((nprach_list+ce_level)->numRepetitionsPerPreambleAttempt) ) ;
......@@ -134,127 +212,994 @@ void add_UL_Resource_node(available_resource_UL_t **head, uint32_t *end_subframe
new_node->prev = iterator;
}
////////////////////////CALVIN TIMING DIAGRAM GENERATOR///////////////////////////
#ifdef TIMING_GENERATOR
uint32_t ii, jj;
for(ii=*end_subframe+(nprach_list+ce_level)->nprach_StartTime; ii<new_node->start_subframe; ++ii){
if(ii >= sim_end_time) break;
for(jj=0; jj<(nprach_list+ce_level)->nprach_NumSubcarriers; ++jj){
ul_scheduled(ii, 0, (nprach_list+ce_level)->nprach_SubcarrierOffset + jj, _NPRACH, 0, (char *)0);
}
}
#endif
////////////////////////CALVIN TIMING DIAGRAM GENERATOR///////////////////////////
*end_subframe += (nprach_list+ce_level)->nprach_Periodicity;
}
/// Use to extend the UL resource grid (5 list) at the end of nprach peroid time
/// void add_UL_Resource(eNB_MAC_INST_NB_IoT *mac_inst)
void add_UL_Resource(void)
{
{
add_UL_Resource_node(&available_resource_UL->sixtone_Head, &available_resource_UL->sixtone_end_subframe, 2);
add_UL_Resource_node(&available_resource_UL->threetone_Head, &available_resource_UL->threetone_end_subframe, 1);
add_UL_Resource_node(&available_resource_UL->singletone1_Head, &available_resource_UL->singletone1_end_subframe, 0);
add_UL_Resource_node(&available_resource_UL->singletone2_Head, &available_resource_UL->singletone2_end_subframe, 0);
add_UL_Resource_node(&available_resource_UL->singletone3_Head, &available_resource_UL->singletone3_end_subframe, 0);
//print_available_UL_resource(); getchar();
}
/*when there is SIB-2 configuration coming to MAC, filled the uplink resource grid*/
void Initialize_Resource(void){
///memory allocate to Head
available_resource_UL = (available_resource_tones_UL_t*)malloc(sizeof(available_resource_tones_UL_t));
available_resource_UL->sixtone_Head = (available_resource_UL_t *)0;
available_resource_UL->threetone_Head = (available_resource_UL_t *)0;
available_resource_UL->singletone1_Head = (available_resource_UL_t *)0;
available_resource_UL->singletone2_Head = (available_resource_UL_t *)0;
available_resource_UL->singletone3_Head = (available_resource_UL_t *)0;
available_resource_UL->sixtone_end_subframe = 0;
available_resource_UL->threetone_end_subframe = 0;
available_resource_UL->singletone1_end_subframe = 0;
available_resource_UL->singletone2_end_subframe = 0;
available_resource_UL->singletone3_end_subframe = 0;
add_UL_Resource();
add_UL_Resource();
printf("Initialization of the UL Resource grid has been done\n");
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;
}
// extend subframe align to si-period
void extend_available_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int max_subframe){ // assume max_subframe is found.
available_resource_DL_t *new_node;
//int temp;
uint32_t i, i_div_si_window;
//uint32_t si_period_div_window;
if(max_subframe > mac_inst->schedule_subframe_DL){
// align to si-period
max_subframe = ((max_subframe%mac_inst->rrc_config.si_window_length)==0)? max_subframe : (((max_subframe/mac_inst->rrc_config.si_window_length)+1)*mac_inst->rrc_config.si_window_length);
//printf("max %d last->end %p\n", max_subframe, available_resource_DL_last);
if(mac_inst->schedule_subframe_DL == available_resource_DL_last->end_subframe){
available_resource_DL_last->end_subframe = max_subframe;
//available_resource_DL_last->DLSF_num += calculate_DLSF(mac_inst, mac_inst->schedule_subframe_DL+1, max_subframe);
}else{
new_node = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
available_resource_DL_last->next = new_node;
new_node->start_subframe = mac_inst->schedule_subframe_DL+1;
new_node->end_subframe = max_subframe;
new_node->next = (available_resource_DL_t *)0;
//new_node->DLSF_num = calculate_DLSF(mac_inst, mac_inst->schedule_subframe_DL+1, max_subframe);
}
// do schedule sibs after extend.
for(i=mac_inst->schedule_subframe_DL;i<max_subframe;i+=mac_inst->rrc_config.si_window_length){
i_div_si_window = i / mac_inst->rrc_config.si_window_length;
if(-1 != mac_inst->sibs_table[i_div_si_window]){
//printf("[sibs%d] %d\n", mac_inst->sibs_table[i_div_si_window], i);
printf("Schedule SIB in \n");
schedule_sibs_NB_IoT(mac_inst, mac_inst->sibs_table[i_div_si_window], i);
printf("Schedule SIB out \n");
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];
return TBS>>3;
}
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
{
LOG_D(MAC,"unknown CE level!\n");
return -1;
}
}
}
return N_rep;
}
mac_inst->schedule_subframe_DL = max_subframe;
}
LOG_I(MAC,"[NB-IoT] Initialization of the DL Resource grid has been done\n");
return ;
int get_I_REP(int N_rep)
{
int i;
for(i = 0; i < 8;i++)
{
if(N_rep == rachrepeat[i])
return i;
}
LOG_D(MAC,"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;
}
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 *temp;
schedule_result_t *iterator, *temp1;
}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;
}
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;
LOG_D(MAC,"[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;
LOG_D(MAC,"[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;
LOG_D(MAC,"[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;
}
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;
LOG_D(MAC,"[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;
LOG_D(MAC,"[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;
return -1;
}
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;
}
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 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);
LOG_D(MAC,"harq result %d, time:%d total ru:%d\n", result, uplink_time, total_ru);
}
if(result == 0)
{
return 0;
}
return -1;
}
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 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_inst, rnti_t rnti, uint8_t *ul_printf_str, uint8_t *dl_printf_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_inst;
UL_result->npusch_format = 0;
UL_result->DCI_release = 1;
UL_result->channel = NPUSCH;
UL_result->rnti = rnti;
UL_result->next = NULL;
//UL_result->printf_str = ul_printf_str;
if(-1 == DCI_subframe){
LOG_D(MAC,"[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_inst;
DL_result->DCI_release = 0;
DL_result->direction = DL;
DL_result->channel = NPDCCH;
DL_result->rnti = rnti;
DL_result->next = NULL;
//DL_result->printf_str = dl_printf_str;
insert_schedule_result(&schedule_result_list_DL, DCI_subframe, DL_result);
LOG_D(MAC,"[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 = 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->prev = node;
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:
if(node!=NULL)
{
// delete
if(node->prev==(available_resource_UL_t *)0)
{
if(NPUSCH_info->tone==sixtone)
available_resource_UL->sixtone_Head = node->next;
else if(NPUSCH_info->tone==threetone)
available_resource_UL->threetone_Head = node->next;
else if(NPUSCH_info->tone==singletone1)
available_resource_UL->singletone1_Head = node->next;
else if(NPUSCH_info->tone==singletone2)
available_resource_UL->singletone2_Head = node->next;
else if(NPUSCH_info->tone==singletone3)
available_resource_UL->singletone3_Head = node->next;
}else{
node->prev->next = node->next;
}
if(node->next!=(available_resource_UL_t *)0)
{
node->next->prev = node->prev;
}else{
node->prev->next = (available_resource_UL_t *)0;
}
free(node);
break;
}
default:
//error
break;
}
}
void add_ue_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint16_t rnti, ce_level_t ce, uint32_t PHR, uint32_t ul_total_buffer){
int32_t i;
UE_list_NB_IoT_t *UE_list = (mac_inst->UE_list_spec + (uint32_t)ce);
for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
if(UE_list->UE_template_NB_IoT[i].active == 0){
UE_list->UE_template_NB_IoT[i].active = 1;
UE_list->UE_template_NB_IoT[i].rnti = rnti;
UE_list->UE_template_NB_IoT[i].PHR = PHR;
UE_list->UE_template_NB_IoT[i].ul_total_buffer = ul_total_buffer;
//New UE setting start
UE_list->UE_template_NB_IoT[i].R_dl = dl_rep[(uint32_t)ce];;
UE_list->UE_template_NB_IoT[i].I_mcs_dl = 0;
UE_list->UE_template_NB_IoT[i].CE_level = (uint32_t)ce;
//assume random select direction
UE_list->UE_template_NB_IoT[i].R_dci = dci_rep[(uint32_t)ce];
UE_list->UE_template_NB_IoT[i].R_max = UE_list->NPDCCH_config_dedicated.R_max;
UE_list->UE_template_NB_IoT[i].R_harq = harq_rep[(uint32_t)ce];
UE_list->UE_template_NB_IoT[i].HARQ_round = 0;
UE_list->UE_template_NB_IoT[i].oldNDI_UL = 0;
UE_list->UE_template_NB_IoT[i].oldNDI_DL = 0;
UE_list->UE_template_NB_IoT[i].multi_tone = 1;
//New UE setting ending
UE_list->UE_template_NB_IoT[i].prev = -1;
if(-1 == UE_list->head){
UE_list->UE_template_NB_IoT[i].next = -1;
}else{
UE_list->UE_template_NB_IoT[i].next = UE_list->head;
}
UE_list->head = i;
return ;
}
}
}
void remove_ue(eNB_MAC_INST_NB_IoT *mac_inst, uint16_t rnti, ce_level_t ce){
int32_t i;
UE_list_NB_IoT_t *UE_list = (mac_inst->UE_list_spec + (uint32_t)ce);
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 == rnti){
UE_list->UE_template_NB_IoT[i].active = 0;
return ;
}
}
}
//Transfrom source into hyperSF, Frame, Subframe format
void convert_system_number(uint32_t source_sf,uint32_t *hyperSF, uint32_t *frame, uint32_t *subframe)
{
if(source_sf>=1024*1024*10)
{
source_sf=source_sf%(1024*1024*10);
}
*hyperSF = (source_sf/10)/1024;
*frame = (source_sf/10)%1024;
*subframe = (source_sf%10240)%10;
}
//Trnasform 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;
//uint8_t flag_printf=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];
while(num_dlsf_require>DLSF_information.num_dlsf_per_period)
{
//flag_printf=1;
period_count++;
num_dlsf_require-=DLSF_information.num_dlsf_per_period;
}
abs_sf_end = abs_sf_start+period_count*mac_inst->sib1_period*10;
//LOG_D(MAC,"[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;
}
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);
//LOG_D(MAC,"[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];
}
}
convert_system_number(abs_sf_end, hyperSF_result, frame_result, subframe_result);
return abs_sf_end;
}
void init_dlsf_info(eNB_MAC_INST_NB_IoT *mac_inst, DLSF_INFO_t *DLSF_info)
{
uint16_t dlsf_num_temp=0;
uint16_t i;
uint16_t j=0;
DLSF_info->sf_to_dlsf_table=(uint16_t*)malloc(mac_inst->sib1_period*10*sizeof(uint16_t));
for(i=0;i<mac_inst->sib1_period*10;++i)
{
if(is_dlsf(mac_inst, i)==1)
{
dlsf_num_temp++;
DLSF_info->sf_to_dlsf_table[i]=dlsf_num_temp;
}
else
{
DLSF_info->sf_to_dlsf_table[i]=dlsf_num_temp;
}
}
DLSF_info->num_dlsf_per_period = dlsf_num_temp;
DLSF_info->dlsf_to_sf_table = (uint16_t*)malloc(dlsf_num_temp*sizeof(uint16_t));
for(i=0;i<mac_inst->sib1_period*10;++i)
{
if(is_dlsf(mac_inst, i)==1)
{
DLSF_info->dlsf_to_sf_table[j]= i;
j++;
}
}
}
void init_tool_sib1(eNB_MAC_INST_NB_IoT *mac_inst){
int i, j;
//int repetition_pattern = 1;// 1:every2frame, 2:every4frame, 3:every8frame, 4:every16frame
for(i=0;i<8;++i){
mac_inst->sib1_flag[(i<<1)+mac_inst->rrc_config.sib1_NB_IoT_sched_config.starting_rf] = 1;
}
for(i=0, j=0;i<64;++i){
if(mac_inst->sib1_flag[i]==1){
++j;
}
mac_inst->sib1_count[i]=j;
}
mac_inst->sib1_period = 256 / mac_inst->rrc_config.sib1_NB_IoT_sched_config.repetitions;
return ;
}
uint32_t calculate_DLSF(eNB_MAC_INST_NB_IoT *mac_inst, int abs_start_subframe, int abs_end_subframe){ //LOG_D(MAC,"calcu %p %d %d\n", mac_inst, abs_start_subframe, abs_end_subframe);
int i;
int num_dlsf=0;
//int diff_subframe = abs_end_subframe - abs_start_subframe;
int start_frame = abs_start_subframe / 10;
int end_frame = abs_end_subframe / 10;
int start_subframe = abs_start_subframe % 10;
int end_subframe = abs_end_subframe % 10;
int start_frame_mod_64 = start_frame & 0x0000003f;
int end_frame_mod_64 = end_frame & 0x0000003f;
int start_frame_div_64 = (start_frame & 0xffffffc0)>>6;
int end_frame_div_64 = (end_frame & 0xffffffc0)>>6;
if(abs_start_subframe > abs_end_subframe){
return calculate_DLSF(mac_inst, abs_start_subframe, (MAX_FRAME*10)+9) + calculate_DLSF(mac_inst, 0, abs_end_subframe);
}
if(start_frame_div_64==end_frame_div_64 && start_frame==end_frame){
for(i=abs_start_subframe;i<=abs_end_subframe;++i){
num_dlsf += is_dlsf(mac_inst, i);
}
}else{
num_dlsf = mac_inst->dlsf_table[end_frame_mod_64];
num_dlsf -= (start_frame_mod_64==0)?0:mac_inst->dlsf_table[start_frame_mod_64-1];
for(i=0;i<start_subframe;++i, --abs_start_subframe){
num_dlsf -= is_dlsf(mac_inst, abs_start_subframe-1);
}
for(i=end_subframe;i<9;++i, ++abs_end_subframe){
num_dlsf -= is_dlsf(mac_inst, abs_end_subframe+1);
}
if(start_frame_div_64!=end_frame_div_64){
num_dlsf+= (472+(end_frame_div_64-start_frame_div_64-1)*472);
}
}
return num_dlsf;
}
int is_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe){
int frame = abs_subframe/10;
int subframe = abs_subframe%10;
return !(subframe==0||subframe==5||((frame&0x1)==0&&subframe==9)||(mac_inst->sib1_flag[frame%mac_inst->sib1_period]==1&&subframe==4));
}
void init_dl_list(eNB_MAC_INST_NB_IoT *mac_inst){
available_resource_DL_t *node;
node = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
node->next = (available_resource_DL_t *)0;
node->prev = (available_resource_DL_t *)0;
available_resource_DL = node;
available_resource_DL_last = node;
node->start_subframe = 0;
node->end_subframe = mac_inst->rrc_config.si_window_length;
mac_inst->schedule_subframe_DL = mac_inst->rrc_config.si_window_length;
// init sibs for first si-window
schedule_sibs(mac_inst, 0, 0);
}
// extend subframe align to si-period
void extend_available_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int max_subframe){ // assume max_subframe is found.
//printf_FUNCTION_IN("[EXTEND DL]");
available_resource_DL_t *new_node;
//int temp;
uint32_t i, i_div_si_window;
//uint32_t si_period_div_window;
//pt = available_resource_DL;
LOG_D(MAC,"[extend DL] max_subframe: %d, current schedule subframe: %d\n", max_subframe, mac_inst->schedule_subframe_DL);
print_available_resource_DL(mac_inst);
if(max_subframe > mac_inst->schedule_subframe_DL){
// align to si-period
max_subframe = ((max_subframe%mac_inst->rrc_config.si_window_length)==0)? max_subframe : (((max_subframe/mac_inst->rrc_config.si_window_length)+1)*mac_inst->rrc_config.si_window_length);
if(mac_inst->schedule_subframe_DL == available_resource_DL_last->end_subframe){
LOG_D(MAC,"[extend DL] last node is align to schedule_sf_dl\n");
available_resource_DL_last->end_subframe = max_subframe;
}else{
LOG_D(MAC,"[extend DL] add new node !\n");
new_node = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
available_resource_DL_last->next = new_node;
new_node->start_subframe = mac_inst->schedule_subframe_DL+1;
new_node->end_subframe = max_subframe;
new_node->next = (available_resource_DL_t *)0;
available_resource_DL_last = new_node;
}
// do schedule sibs after extend.
for(i=mac_inst->schedule_subframe_DL;i<max_subframe;i+=mac_inst->rrc_config.si_window_length){
i_div_si_window = (i / mac_inst->rrc_config.si_window_length)%256;
if(-1 != mac_inst->sibs_table[i_div_si_window]){
LOG_D(MAC,"[sibs%d] %d\n", mac_inst->sibs_table[i_div_si_window], i);
schedule_sibs(mac_inst, mac_inst->sibs_table[i_div_si_window], i);
}
}
mac_inst->schedule_subframe_DL = max_subframe;
}
//printf_FUNCTION_OUT("[EXTEND DL]");
return ;
}
void maintain_available_resource(eNB_MAC_INST_NB_IoT *mac_inst){
//printf_FUNCTION_IN("[MAINTAIN]");
available_resource_DL_t *pfree, *iterator;
available_resource_UL_t *pfree2, *iterator2;
schedule_result_t *iterator1;
if(available_resource_DL != (available_resource_DL_t *)0){
if(mac_inst->current_subframe >= available_resource_DL->end_subframe){
pfree = available_resource_DL;
if(available_resource_DL->next == (available_resource_DL_t *)0){
LOG_D(MAC,"[maintain_available_resource]=====t:%d=====dl resource list next is NULL %d\n", mac_inst->current_subframe, available_resource_DL->end_subframe);
available_resource_DL = (available_resource_DL_t *)0;
}else{
LOG_D(MAC,"[maintain_available_resource]=====t:%d=====dl resource list remove next:%d-%d\n", mac_inst->current_subframe, available_resource_DL->next->start_subframe, available_resource_DL->next->end_subframe);
available_resource_DL = available_resource_DL->next;
available_resource_DL->prev = (available_resource_DL_t *)0;
}
free((available_resource_DL_t *)pfree);
}else{
available_resource_DL->start_subframe = mac_inst->current_subframe;
}
// UL
iterator2 = available_resource_UL->singletone1_Head;
if(iterator2 != (available_resource_UL_t *)0){
if(mac_inst->current_subframe >= iterator2->end_subframe){
pfree2 = iterator2;
available_resource_UL->singletone1_Head = iterator2->next;
available_resource_UL->singletone1_Head->prev = (available_resource_UL_t *)0;
free((available_resource_UL_t *)pfree2);
}else{
iterator2->start_subframe = mac_inst->current_subframe;
}
}
iterator2 = available_resource_UL->singletone2_Head;
if(iterator2 != (available_resource_UL_t *)0){
if(mac_inst->current_subframe >= iterator2->end_subframe){
pfree2 = iterator2;
available_resource_UL->singletone2_Head = iterator2->next;
available_resource_UL->singletone2_Head->prev = (available_resource_UL_t *)0;
free((available_resource_UL_t *)pfree2);
}else{
iterator2->start_subframe = mac_inst->current_subframe;
}
}
iterator2 = available_resource_UL->singletone3_Head;
if(iterator2 != (available_resource_UL_t *)0){
if(mac_inst->current_subframe >= iterator2->end_subframe){
pfree2 = iterator2;
available_resource_UL->singletone3_Head = iterator2->next;
available_resource_UL->singletone3_Head->prev = (available_resource_UL_t *)0;
free((available_resource_UL_t *)pfree2);
}else{
iterator2->start_subframe = mac_inst->current_subframe;
}
}
iterator2 = available_resource_UL->sixtone_Head;
if(iterator2 != (available_resource_UL_t *)0){
if(mac_inst->current_subframe >= iterator2->end_subframe){
pfree2 = iterator2;
available_resource_UL->sixtone_Head = iterator2->next;
available_resource_UL->sixtone_Head->prev = (available_resource_UL_t *)0;
free((available_resource_UL_t *)pfree2);
}else{
iterator2->start_subframe = mac_inst->current_subframe;
}
}
iterator2 = available_resource_UL->threetone_Head;
if(iterator2 != (available_resource_UL_t *)0){
if(mac_inst->current_subframe >= iterator2->end_subframe){
pfree2 = iterator2;
available_resource_UL->threetone_Head = iterator2->next;
available_resource_UL->threetone_Head->prev = (available_resource_UL_t *)0;
free((available_resource_UL_t *)pfree2);
}else{
iterator2->start_subframe = mac_inst->current_subframe;
}
}
if(mac_inst->current_subframe == 0){
// DL available cross zero
iterator = available_resource_DL;
while(iterator != (available_resource_DL_t *)0){
if(iterator->start_subframe >= MAX_SUBFRAME)
iterator->start_subframe -= MAX_SUBFRAME;
if(iterator->end_subframe >= MAX_SUBFRAME)
iterator->end_subframe -= MAX_SUBFRAME;
iterator = iterator->next;
}
if(mac_inst->schedule_subframe_DL >= MAX_SUBFRAME)
mac_inst->schedule_subframe_DL -= MAX_SUBFRAME;
// UL available cross zero
iterator2 = available_resource_UL->sixtone_Head;
while(iterator2 != (available_resource_UL_t *)0){
if(iterator2->start_subframe >= MAX_SUBFRAME)
iterator2->start_subframe -= MAX_SUBFRAME;
if(iterator2->end_subframe >= MAX_SUBFRAME)
iterator2->end_subframe -= MAX_SUBFRAME;
iterator2 = iterator2->next;
}
iterator2 = available_resource_UL->threetone_Head;
while(iterator2 != (available_resource_UL_t *)0){
if(iterator2->start_subframe >= MAX_SUBFRAME)
iterator2->start_subframe -= MAX_SUBFRAME;
if(iterator2->end_subframe >= MAX_SUBFRAME)
iterator2->end_subframe -= MAX_SUBFRAME;
iterator2 = iterator2->next;
}
iterator2 = available_resource_UL->singletone3_Head;
while(iterator2 != (available_resource_UL_t *)0){
if(iterator2->start_subframe >= MAX_SUBFRAME)
iterator2->start_subframe -= MAX_SUBFRAME;
if(iterator2->end_subframe >= MAX_SUBFRAME)
iterator2->end_subframe -= MAX_SUBFRAME;
iterator2 = iterator2->next;
}
iterator2 = available_resource_UL->singletone1_Head;
while(iterator2 != (available_resource_UL_t *)0){
if(iterator2->start_subframe >= MAX_SUBFRAME)
iterator2->start_subframe -= MAX_SUBFRAME;
if(iterator2->end_subframe >= MAX_SUBFRAME)
iterator2->end_subframe -= MAX_SUBFRAME;
iterator2 = iterator2->next;
}
iterator2 = available_resource_UL->singletone2_Head;
while(iterator2 != (available_resource_UL_t *)0){
if(iterator2->start_subframe >= MAX_SUBFRAME)
iterator2->start_subframe -= MAX_SUBFRAME;
if(iterator2->end_subframe >= MAX_SUBFRAME)
iterator2->end_subframe -= MAX_SUBFRAME;
iterator2 = iterator2->next;
}
if(available_resource_UL->singletone1_end_subframe >= MAX_SUBFRAME)
available_resource_UL->singletone1_end_subframe -= MAX_SUBFRAME;
if(available_resource_UL->singletone2_end_subframe >= MAX_SUBFRAME)
available_resource_UL->singletone2_end_subframe -= MAX_SUBFRAME;
if(available_resource_UL->singletone3_end_subframe >= MAX_SUBFRAME)
available_resource_UL->singletone3_end_subframe -= MAX_SUBFRAME;
if(available_resource_UL->sixtone_end_subframe >= MAX_SUBFRAME)
available_resource_UL->sixtone_end_subframe -= MAX_SUBFRAME;
if(available_resource_UL->threetone_end_subframe >= MAX_SUBFRAME)
available_resource_UL->threetone_end_subframe -= MAX_SUBFRAME;
// DL result cross zero
iterator1 = schedule_result_list_DL;
while(iterator1 != (schedule_result_t *)0){
if(iterator1->output_subframe >= MAX_SUBFRAME)
iterator1->output_subframe -= MAX_SUBFRAME;
if(iterator1->end_subframe >= MAX_SUBFRAME)
iterator1->end_subframe -= MAX_SUBFRAME;
iterator1 = iterator1->next;
}
// UL result cross zero
iterator1 = schedule_result_list_UL;
while(iterator1 != (schedule_result_t *)0){
if(iterator1->output_subframe >= MAX_SUBFRAME)
iterator1->output_subframe -= MAX_SUBFRAME;
if(iterator1->end_subframe >= MAX_SUBFRAME)
iterator1->end_subframe -= MAX_SUBFRAME;
iterator1 = iterator1->next;
}
}
}
//printf_FUNCTION_OUT("[MAINTAIN]");
return ;
}
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){
//printf_FUNCTION_IN("[FILL DL]");
available_resource_DL_t *temp;
schedule_result_t *iterator, *temp1;
// divided into two node
// keep one node(align left or right)
// delete node
//LOG_D(MAC,"fill dl test1\n");
int align_left = (node->start_subframe==start_subframe)||(calculate_DLSF(mac_inst, node->start_subframe, start_subframe-1) == 0);
int align_right = (end_subframe==node->end_subframe)||(calculate_DLSF(mac_inst, end_subframe+1, node->end_subframe) == 0);
//print_available_resource_DL();
//DEBUG("[debug] align : %d %d\n", align_left, align_right);
//LOG_D(MAC,"fill dl test2\n");
switch(align_left+align_right){
case 0:
// divided into two node
// divided into two node, always insert before original node, so won't happen that temp is the last node of the list.
// A | node | B
// A | temp | node | B
temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
if(node->prev){
node->prev->next = temp;
}else{
available_resource_DL = temp;
}
temp->prev = node->prev;
temp->next = node;
node->prev = temp;
//node->next don't need to change
temp->start_subframe = node->start_subframe;
temp->end_subframe = start_subframe - 1;
node->start_subframe = end_subframe + 1;
node->DLSF_num = calculate_DLSF(mac_inst, node->start_subframe, node->end_subframe);
temp->DLSF_num = calculate_DLSF(mac_inst, temp->start_subframe, temp->end_subframe);
break;
case 1:
// keep one node
......@@ -264,7 +1209,6 @@ void fill_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, available_resource_DL_t *no
node->end_subframe = start_subframe - 1 ;
}
node->DLSF_num = calculate_DLSF(mac_inst, node->start_subframe, node->end_subframe);
break;
case 2:
// delete
......@@ -311,13 +1255,55 @@ void fill_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, available_resource_DL_t *no
}
}
}
//printf_FUNCTION_OUT("[FILL DL]");
}
// 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;
}
}
}
available_resource_DL_t *check_sibs_resource(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t check_start_subframe, uint32_t check_end_subframe, uint32_t num_subframe, uint32_t *residual_subframe, uint32_t *out_last_subframe, uint32_t *out_first_subframe){
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){
available_resource_DL_t *pt;
uint32_t num_dlsf;
uint8_t output = 0x0;
pt = available_resource_DL;
// TODO find the pt which can cover part of check_start_subframe, e.g. 1280-> 1281-1440
while((available_resource_DL_t *)0 != pt){
if(pt->start_subframe <= check_start_subframe && pt->end_subframe >= check_start_subframe){
......@@ -325,16 +1311,10 @@ available_resource_DL_t *check_sibs_resource(eNB_MAC_INST_NB_IoT *mac_inst, uint
}
pt = pt->next;
}
//print_available_resource_DL();
//DEBUG("sibs %d", check_start_subframe);
if((available_resource_DL_t *)0 == pt){
return (available_resource_DL_t *)0;
}
num_dlsf = calculate_DLSF(mac_inst, check_start_subframe, pt->end_subframe);
if((available_resource_DL_t *)0 == pt){
......@@ -377,234 +1357,134 @@ available_resource_DL_t *check_sibs_resource(eNB_MAC_INST_NB_IoT *mac_inst, uint
}
}
uint32_t calculate_DLSF(eNB_MAC_INST_NB_IoT *mac_inst, int abs_start_subframe, int abs_end_subframe){
int i;
int num_dlsf=0;
//int diff_subframe = abs_end_subframe - abs_start_subframe;
int start_frame = abs_start_subframe / 10;
int end_frame = abs_end_subframe / 10;
int start_subframe = abs_start_subframe % 10;
int end_subframe = abs_end_subframe % 10;
int start_frame_mod_64 = start_frame & 0x0000003f;
int end_frame_mod_64 = end_frame & 0x0000003f;
int start_frame_div_64 = (start_frame & 0xffffffc0)>>6;
int end_frame_div_64 = (end_frame & 0xffffffc0)>>6;
if(start_frame > end_frame){
return calculate_DLSF(mac_inst, abs_start_subframe, MAX_FRAME*10+9) + calculate_DLSF(mac_inst, 0, abs_end_subframe);
}
if(start_frame_div_64==end_frame_div_64 && start_frame==end_frame){
for(i=abs_start_subframe;i<=abs_end_subframe;++i){
num_dlsf += is_dlsf(mac_inst, i);
}
}else{
num_dlsf = mac_inst->dlsf_table[end_frame_mod_64];
num_dlsf -= (start_frame_mod_64==0)?0:mac_inst->dlsf_table[start_frame_mod_64-1];
for(i=0;i<start_subframe;++i, --abs_start_subframe){
num_dlsf -= is_dlsf(mac_inst, abs_start_subframe-1);
}
for(i=end_subframe;i<9;++i, ++abs_end_subframe){
num_dlsf -= is_dlsf(mac_inst, abs_end_subframe+1);
}
if(start_frame_div_64!=end_frame_div_64){
num_dlsf+= (472+(end_frame_div_64-start_frame_div_64-1)*472);
}
}
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){
void print_available_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst){
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;
}
int i=0;
LOG_D(MAC,"=== print available resource === t=%d\nsched subframe: %d, list end: %d-%d\n", mac_inst->current_subframe, mac_inst->schedule_subframe_DL, available_resource_DL_last->start_subframe, available_resource_DL_last->end_subframe);
while(pt){
LOG_D(MAC,"[%2d] %p %3d-%3d\n", i, pt, pt->start_subframe, pt->end_subframe);
pt = pt->next;
}
LOG_D(MAC,"\n");
}
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;
void print_schedule_result(void){
schedule_result_t *iterator_dl = schedule_result_list_DL;
schedule_result_t *iterator_ul = schedule_result_list_UL;
schedule_result_t *iterator;
int i = 0;
char str[20];
char str1[20];
char str2[20];
LOG_D(MAC,"=== print schedule result ===\n");
while((schedule_result_t *)0 != iterator_dl || (schedule_result_t *)0 != iterator_ul){
if((schedule_result_t *)0 == iterator_dl){
iterator = iterator_ul;
iterator_ul = iterator_ul->next;
}
else if((schedule_result_t *)0 == iterator_ul){
iterator = iterator_dl;
iterator_dl = iterator_dl->next;
}else{
return (available_resource_DL_t *)0;
if(iterator_ul->output_subframe < iterator_dl->output_subframe){
iterator = iterator_ul;
iterator_ul = iterator_ul->next;
}else{
iterator = iterator_dl;
iterator_dl = iterator_dl->next;
}
}
}
}
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;
if(iterator->rnti == P_RNTI){
sprintf(str, " PAGING");
}
else if(iterator->rnti == SI_RNTI){
sprintf(str, "SI-RNTI");
}
else if(iterator->rnti <= RA_RNTI_HIGH && iterator->rnti >= RA_RNTI_LOW){
sprintf(str, "RA-RNTI");
}else{
*list = node;
sprintf(str, "UE%05d", iterator->rnti-C_RNTI_LOW);
}
}
}
}
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;
}
}
if(iterator->direction == DL){
sprintf(str1, "DL");
}else{
sprintf(str1, "UL");
}
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;
switch(iterator->channel){
case NPDCCH:
sprintf(str2, "NPDCCH");
break;
case NPDSCH:
sprintf(str2, "NPDSCH");
break;
case NPUSCH:
sprintf(str2, "NPUSCH");
break;
default:
break;
}
LOG_D(MAC,"[%2d][%s][%s][%s] output(%4d)\n", i++, str, str1, str2, iterator->output_subframe);
/* if((uint8_t *)0 != iterator->printf_str){
LOG_D(MAC," printf: %s\n", iterator->printf_str);
}else{
LOG_D(MAC,"\n");
}*/
}
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;
void print_schedule_result_DL(void){
schedule_result_t *iterator = schedule_result_list_DL;
int i=0;
char str[20];
LOG_D(MAC,"=== print schedule result DL ===\n");
while((schedule_result_t *)0 != iterator){
if(iterator->rnti == P_RNTI){
sprintf(str, " PAGE");
}
else if(iterator->rnti == SI_RNTI){
sprintf(str, " SI");
}
else if(iterator->rnti <= RA_RNTI_HIGH && iterator->rnti >= RA_RNTI_LOW){
sprintf(str, " RA");
}else{
sprintf(str, "UE%03d", iterator->rnti-C_RNTI_LOW);
}
LOG_D(MAC,"[%2d][%s][""DL""] output(%4d)\n", i++, str, iterator->output_subframe);
/*if((uint8_t *)0 != iterator->printf_str){
LOG_D(MAC," printf: %s\n", iterator->printf_str);
}else{
LOG_D(MAC,"\n");
}*/
iterator = iterator->next;
}
}
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;
}
void print_schedule_result_UL(void){
schedule_result_t *iterator = schedule_result_list_UL;
int i=0;
char str[20];
LOG_D(MAC,"=== print schedule result UL ===\n");
while((schedule_result_t *)0 != iterator){
sprintf(str, "UE%03d", iterator->rnti-C_RNTI_LOW);
LOG_D(MAC,"[%2d][%s][""UL""] output(%4d)\n", i++, str, iterator->output_subframe);
/*if((uint8_t *)0 != iterator->printf_str){
LOG_D(MAC," printf: %s\tnext %p\n", iterator->printf_str, iterator->next);
}else{
LOG_D(MAC,"\n");
}*/
iterator = iterator->next;
}
return 0;
}
uint32_t get_scheduling_delay(uint32_t I_delay, uint32_t R_max)
......@@ -620,285 +1500,95 @@ uint32_t get_scheduling_delay(uint32_t I_delay, uint32_t R_max)
if(I_delay<=4)
return 4*I_delay;
else
return (uint32_t)(2<<I_delay);//pow(2, I_delay);
return (uint32_t)(2<<I_delay);
}
else
{
return (uint32_t)(16<<(I_delay-1));//*pow(2, I_delay-1);
return (uint32_t)(16<<(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;
}
#if 0
uint8_t *parse_ulsch_header( uint8_t *mac_header,
uint8_t *num_ce,
uint8_t *num_sdu,
uint8_t *rx_ces,
uint8_t *rx_lcids,
uint16_t *rx_lengths,
uint16_t tb_length ){
///threetone
available_resource = available_resource_UL->threetone_Head;
uint8_t not_done=1, num_ces=0, num_sdus=0, lcid,num_sdu_cnt;
uint8_t *mac_header_ptr = mac_header;
uint16_t length, ce_len=0;
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;
}
while(not_done==1){
///singletone1
available_resource = available_resource_UL->singletone1_Head;
if(((SCH_SUBHEADER_FIXED*)mac_header_ptr)->E == 0){
not_done = 0;
}
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;
}
lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID;
///singletone1
available_resource = available_resource_UL->singletone2_Head;
if(lcid < EXTENDED_POWER_HEADROOM){
if (not_done==0) { // last MAC SDU, length is implicit
mac_header_ptr++;
length = tb_length-(mac_header_ptr-mac_header)-ce_len;
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;
}
for(num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++){
length -= rx_lengths[num_sdu_cnt];
}
}else{
if(((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0){
length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
mac_header_ptr += 2;//sizeof(SCH_SUBHEADER_SHORT);
}else{ // F = 1
length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff);
mac_header_ptr += 3;//sizeof(SCH_SUBHEADER_LONG);
}
}
///singletone1
available_resource = available_resource_UL->singletone3_Head;
rx_lcids[num_sdus] = lcid;
rx_lengths[num_sdus] = length;
num_sdus++;
}else{ // This is a control element subheader POWER_HEADROOM, BSR and CRNTI
if(lcid == SHORT_PADDING){
mac_header_ptr++;
}else{
rx_ces[num_ces] = lcid;
num_ces++;
mac_header_ptr++;
if(lcid==LONG_BSR){
ce_len+=3;
}else if(lcid==CRNTI){
ce_len+=2;
}else if((lcid==POWER_HEADROOM) || (lcid==TRUNCATED_BSR)|| (lcid== SHORT_BSR)) {
ce_len++;
}else{
// wrong lcid
}
}
}
}
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;
}
*num_ce = num_ces;
*num_sdu = num_sdus;
return(mac_header_ptr);
}
#endif
// maybe we can try to use hash table to enhance searching time.
// calvin
// maybe we can try to use hash table to enhance searching time.
UE_TEMPLATE_NB_IoT *get_ue_from_rnti(eNB_MAC_INST_NB_IoT *inst, rnti_t rnti){
uint32_t i;
for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
if(inst->UE_list_spec->UE_template_NB_IoT[i].active == 1){
if(inst->UE_list_spec->UE_template_NB_IoT[i].rnti == rnti){
return &inst->UE_list_spec->UE_template_NB_IoT[i];
}
}
}
return (UE_TEMPLATE_NB_IoT *)0;
}
\ No newline at end of file
uint32_t i;
for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
if(inst->UE_list_spec->UE_template_NB_IoT[i].active == 1){
if(inst->UE_list_spec->UE_template_NB_IoT[i].rnti == rnti){
return &inst->UE_list_spec->UE_template_NB_IoT[i];
}
}
}
return (UE_TEMPLATE_NB_IoT *)0;
}
......@@ -21,6 +21,8 @@
//#include "COMMON/mac_rrc_primitives.h"
//IF_Module_NB_IoT_t *if_inst_NB_IoT;
//NB-IoT--------------------------------------
eNB_MAC_INST_NB_IoT *mac_inst;
......@@ -70,6 +72,13 @@ 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 int rawindow[8] = {2, 3, 4, 5, 6, 7, 8, 10};
const int rmax[12] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};
const double gvalue[8] = {1.5f, 2, 4, 8, 16, 32, 48, 64};
const int candidate[4] = {1, 2, 4, 8};
const double pdcchoffset[4] = {0, 0.125f, 0.25f, 0.375f};
const int dlrepeat[16] = {1, 2, 4, 8, 16, 32, 64, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048};
const uint32_t RU_table[8]={1,2,3,4,5,6,8,10};
const uint32_t scheduling_delay[4]={8,16,32,64};
......@@ -112,6 +121,13 @@ 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};
int extend_space[2] = {256, 256};
int extend_alpha_offset[2] = {10, 10};
int uss_space = 320;
int uss_alpha_offset = 10;
const int si_repetition_pattern[4] = {20, 40, 80, 160};
#endif
......
......@@ -71,9 +71,9 @@ void UL_indication_NB_IoT(UL_IND_NB_IoT_t *UL_INFO)
abs_subframe = UL_INFO->frame*10+UL_INFO->subframe;
LOG_I(MAC,"Enter scheduler in subframe %d\n",abs_subframe);
//LOG_I(MAC,"Enter scheduler in subframe %d\n",abs_subframe);
//scheduler here
//Schedule subframe should be next four subframe, means that UL_INFO->frame*10+UL_INFO->subframe + 4
eNB_dlsch_ulsch_scheduler_NB_IoT(mac_inst,abs_subframe);
LOG_I(MAC,"After scheduler\n");
}
\ No newline at end of file
......@@ -106,7 +106,7 @@ uint8_t do_MIB_NB_IoT(
/*
* systemFrameNumber-MSB: (TS 36.331 pag 576)
* define the 4 MSB of the SFN (10 bits). The last significant 6 bits will be acquired implicitly by decoding the NPBCH
* NOTE: 6 LSB will be used for counting the 64 radio frames in the TTI period (640 ms) that is exactly the MIB period
* NOTE: 6 LSB will be used for counting the 64 frames in the TTI period (640 ms) that is exactly the MIB period
*
* hyperSFN-LSB:
* indicates the 2 least significant bits of the HSFN. The remaining 8 bits are present in SIB1-NB
......
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