/*! \file eNB_scheduler_RA_NB_IoT.c * \brief functions used in Random access scheduling * \author NTUST BMW Lab./ * \date 2017 * \email: * \version 1.0 * */ #include "defs_NB_IoT.h" #include "proto_NB_IoT.h" #include "extern_NB_IoT.h" unsigned char str1[] = "rar_dci"; unsigned char str2[] = "rar"; unsigned char str3[] = "msg4_dci"; unsigned char str4[] = "msg4"; unsigned char str5[] = "ack_msg4"; unsigned char str6[] = "msg3_dci(retransmit)"; unsigned char str7[] = "msg3(retransmit)"; unsigned char str8[] = "msg4_dci(retransmit)"; unsigned char str9[] = "msg4(retransmit)"; unsigned char str10[] = "ack_msg4(retransmit)"; unsigned char str11[] = "msg3"; unsigned char str12[] = "msg3(retransmit)"; /*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){ int i; RA_TEMPLATE_NB_IoT *msg2_list_tail = mac_inst->RA_msg2_list.tail; 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++); for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){ if(0 == mac_inst->RA_template[i].active){ migrate_node = &mac_inst->RA_template[i]; break; } } 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); return ; } migrate_node->active = 1; migrate_node->preamble_index = preamble_index; migrate_node->ce_level = ce_level; migrate_node->ra_rnti = (sfn_id>>2) + 1; migrate_node->ta = ta; migrate_node->next = (RA_template_NB_IoT *)0; migrate_node->prev = (RA_template_NB_IoT *)0; // insert to end of list if((RA_template_NB_IoT *)0 == mac_inst->RA_msg2_list.head){ mac_inst->RA_msg2_list.head = migrate_node; }else{ // not empty mac_inst->RA_msg2_list.tail->next = migrate_node; migrate_node->prev = mac_inst->RA_msg2_list.tail; } mac_inst->RA_msg2_list.tail = migrate_node; }*/ // 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); } 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; } msg3_nodes = msg3_nodes->next; } return ; } void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){ RA_TEMPLATE_NB_IoT *msg2_nodes = mac_inst->RA_msg2_list.head; //RA_TEMPLATE_NB_IoT *msg3_list_tail = mac_inst->RA_msg3_list.tail; RA_TEMPLATE_NB_IoT *migrate_node; schedule_result_t *dci_result, *msg2_result; DCIFormatN0_t *dci_n0; DCIFormatN1_t *dci_n1_rar; available_resource_DL_t *dci_node, *msg2_node; 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 dci_candidate, i, num_candidate; int msg2_i_delay; int msg3_scheduling_delay; static uint16_t tc_rnti = 0x0101; int rep=1; sched_temp_UL_NB_IoT_t npusch_info; int fail_num = 0; while((RA_TEMPLATE_NB_IoT *)0 != msg2_nodes){ fail=0; rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg2_nodes->ce_level].mac_npdcch_NumRepetitions_RA_NB_IoT;//32; num_candidate = 8;//rmax / r; r = rmax/num_candidate; num_dci_subframe = r; dci_subframe = mac_inst->current_subframe; for(dci_candidate=0; dci_candidate<num_candidate; ++dci_candidate){ while(!is_dlsf(mac_inst, dci_subframe)){ ++dci_subframe; } dci_node = (available_resource_DL_t *)check_resource_DL(mac_inst, dci_subframe, num_dci_subframe, &dci_end_subframe, &dci_first_subframe); if((available_resource_DL_t *)0 != dci_node){ //dci_subframe += dci_candidate*num_dci_subframe; break; } res = num_dci_subframe; while(res != 0){ // maybe would cost lots of time to search if(is_dlsf(mac_inst, dci_subframe)){ res--; } dci_subframe++; } } if(num_candidate==dci_candidate){ fail|=0x1; } // check msg2 resource uint32_t TBS, I_tbs, I_mcs, I_sf, Nrep; I_mcs = get_I_mcs_NB_IoT(msg2_nodes->ce_level); I_tbs = I_mcs; TBS = get_tbs(7, I_tbs, &I_sf); // rar 7 bytes Nrep = dl_rep[msg2_nodes->ce_level]; num_msg2_subframe = get_num_sf(I_sf) * Nrep; //num_msg2_subframe = 8; msg2_i_delay = find_suit_i_delay(rmax, r, dci_candidate); for(i=0; i<8; ++i, ++msg2_i_delay){ msg2_i_delay = (msg2_i_delay==8)?0:msg2_i_delay; msg2_subframe = dci_end_subframe+4+get_scheduling_delay(msg2_i_delay, rmax); msg2_node = (available_resource_DL_t *)check_resource_DL(mac_inst, msg2_subframe, num_msg2_subframe, &msg2_end_subframe, &msg2_first_subframe); if((available_resource_DL_t *)0 != msg2_node){ break; } } if(-1==msg2_i_delay){ fail|=0x2; } // check msg3 resource rep = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg2_nodes->ce_level].mac_numRepetitionsPerPreambleAttempt_NB_IoT; msg3_subframe = msg2_end_subframe; uint32_t Iru = 0, mcs, Nru; uint32_t mappedMcsIndex = 4; // assume all ue supported multi-tone mcs = mapped_mcs[msg2_nodes->ce_level][mappedMcsIndex]; // assume all ue supported multi-tone TBS = get_TBS_UL_NB_IoT(mcs,1,Iru); while((TBS<11)&&(Iru<=7)){ // 88 bits Iru++; TBS=get_TBS_UL_NB_IoT(mcs,1,Iru); } Nru = RU_table[Iru]; for(msg3_scheduling_delay=0; msg3_scheduling_delay<4; ++msg3_scheduling_delay){ // 36.213 Table 16.3.3-1 Imcs=3'b000 Nru=4 if(0==Check_UL_resource(msg3_subframe+msg3_scheduling_delay_table[msg3_scheduling_delay]+1, Nru*rep, &npusch_info, 1, 0)){ //1: multi-tones 0: single-tone. 1: format 2(ack/nack) 0: format 1 break; } } if(4==msg3_scheduling_delay){ fail|=0x4; } if(0 < fail){ fail_num++; printf("[%04d][RA scheduler][MSG2] fail vector %d\n", mac_inst->current_subframe, fail); //SCHEDULE_LOG("[%04d][RA scheduler][MSG2] rnti: %d preamble: %d fail vector %d\n", mac_inst->current_subframe, msg2_nodes->ra_rnti, msg2_nodes->preamble_index, fail); msg2_nodes = msg2_nodes->next; }else{ //SCHEDULE_LOG("[%04d][RA scheduler][MSG2] rnti: %d preamble: %d success\n", mac_inst->current_subframe, msg2_nodes->ra_rnti, msg2_nodes->preamble_index); dci_result = (schedule_result_t *)malloc(sizeof(schedule_result_t)); msg2_result = (schedule_result_t *)malloc(sizeof(schedule_result_t)); dci_n0 = (DCIFormatN0_t *)malloc(sizeof(DCIFormatN0_t)); dci_n1_rar = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t)); fill_rar_NB_IoT(mac_inst, msg2_nodes, msg3_scheduling_delay, rep, &npusch_info); msg2_nodes->wait_msg3_ack = 1; // dci entity dci_n1_rar->type = 1; dci_n1_rar->orderIndicator = 0; dci_n1_rar->Scheddly = msg2_i_delay; dci_n1_rar->ResAssign = 0; dci_n1_rar->mcs = 0; dci_n1_rar->RepNum = 0; // 36.213 table 16.4.1.3-2, 8 candidates dci_n1_rar->ndi = 0; // ndi is useless in RAR 36.212 says the feild is reserved dci_n1_rar->HARQackRes = 0; // no HARQ procedure in RAR 36.212 says the feild is reserved dci_n1_rar->DCIRep = 0; // 36.213 table 16.6-1 R=Rmax/8 // for dci dci_result->output_subframe = dci_first_subframe;//dci_subframe; dci_result->end_subframe = dci_end_subframe; dci_result->sdu_length = 0; dci_result->direction = DL; dci_result->DCI_release = 0; dci_result->channel = NPDCCH; dci_result->rnti = msg2_nodes->ra_rnti;//ra_rnti; dci_result->rnti_type = 1; dci_result->npusch_format = 0; //useless dci_result->R_harq = 0; dci_result->next = (schedule_result_t *)0; dci_result->DCI_pdu = (void *)dci_n1_rar; dci_result->debug_str = &str1[0]; // for msg2 msg2_result->output_subframe = msg2_first_subframe;//msg2_subframe; msg2_result->end_subframe = msg2_end_subframe; msg2_result->sdu_length = 56; // rar size msg2_result->DLSCH_pdu = msg2_nodes->rar_buffer; msg2_result->direction = DL; msg2_result->DCI_release = 1; msg2_result->channel = NPDSCH; msg2_result->rnti = msg2_nodes->ra_rnti;//ra_rnti; msg2_result->rnti_type = 1; msg2_result->npusch_format = 0; //useless msg2_result->R_harq = 0; msg2_result->next = (schedule_result_t *)0; msg2_result->DCI_pdu = (void *)dci_n1_rar; msg2_result->debug_str = str2; msg2_result->rar_buffer = msg2_nodes->rar_buffer; // for msg3(fake DCI N0) dci_n0->type = 0; dci_n0->scind = npusch_info.subcarrier_indication; dci_n0->ResAssign = 0; dci_n0->mcs = 0; dci_n0->ndi = 1; dci_n0->Scheddly = msg3_scheduling_delay; dci_n0->RepNum = rep; dci_n0->rv = 0; dci_n0->DCIRep = 1;//get_DCI_REP() msg2_nodes->ue_rnti = tc_rnti; printf("[%04d][RA scheduler][MSG2] RARDCI %d-%d RAR %d-%d MSG3 %d-%d\n", mac_inst->current_subframe, dci_first_subframe, dci_end_subframe, msg2_first_subframe, msg2_end_subframe, npusch_info.sf_start, npusch_info.sf_end); // fill dci resource fill_resource_DL(mac_inst, dci_node, dci_first_subframe, dci_end_subframe, dci_result); // fill msg2 resource fill_resource_DL(mac_inst, msg2_node, msg2_first_subframe, msg2_end_subframe, msg2_result); // fill msg3 resource generate_scheduling_result_UL(-1, -1, npusch_info.sf_start, npusch_info.sf_end, dci_n0, tc_rnti, str11, (void *)0); adjust_UL_resource_list(&npusch_info); //simulate_rx(&simulate_rx_msg3_list, tc_rnti, npusch_info.sf_start); migrate_node = msg2_nodes; //migrate_node->ue_rnti = tc_rnti; tc_rnti++; msg2_nodes = msg2_nodes->next; // maintain list if((RA_TEMPLATE_NB_IoT *)0 == migrate_node->prev){ // first node mac_inst->RA_msg2_list.head = migrate_node->next; // including null }else{ // not first node migrate_node->prev->next = migrate_node->next; // including null } if((RA_TEMPLATE_NB_IoT *)0 == migrate_node->next){ // last node mac_inst->RA_msg2_list.tail = migrate_node->prev; // including null }else{ // not last node migrate_node->next->prev = migrate_node->prev; // including null } // migrate to next list // insert to end of list migrate_node->next = (RA_TEMPLATE_NB_IoT *)0; migrate_node->prev = (RA_TEMPLATE_NB_IoT *)0; if((RA_TEMPLATE_NB_IoT *)0 == mac_inst->RA_msg3_list.head){ mac_inst->RA_msg3_list.head = migrate_node; }else{ // not empty mac_inst->RA_msg3_list.tail->next = migrate_node; migrate_node->prev = mac_inst->RA_msg3_list.tail; } mac_inst->RA_msg3_list.tail = migrate_node; } } //SCHEDULE_LOG("[%04d][RA scheduler][MSG2] failed number: %d\n", mac_inst->current_subframe, fail_num); return ; } // msg4 scheduling: both first time or retransmit would be scheduled in this function(msg4_list). void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){ RA_TEMPLATE_NB_IoT *msg4_nodes = mac_inst->RA_msg4_list.head; available_resource_DL_t *dci_node, *msg4_node; int rmax, fail, r; int dci_subframe, dci_end_subframe, dci_first_subframe, num_dci_subframe; int msg4_subframe, msg4_end_subframe, msg4_first_subframe, num_msg4_subframe; int harq_subframe, harq_end_subframe; int dci_candidate, num_candidate; int msg4_i_delay, i, res, rep; int end_flagHARQ, HARQ_delay; sched_temp_UL_NB_IoT_t HARQ_info; schedule_result_t *dci_result; schedule_result_t *msg4_result; schedule_result_t *harq_result; msg4_node = (available_resource_DL_t *)0; //print_available_resource_DL(); while((RA_TEMPLATE_NB_IoT *)0 != msg4_nodes){ if(msg4_nodes->wait_msg4_ack == 0){ fail=0; // check dci resource rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg4_nodes->ce_level].mac_npdcch_NumRepetitions_RA_NB_IoT;//32; num_candidate = 8;//rmax / r; r = rmax/num_candidate; num_dci_subframe = r; dci_subframe = mac_inst->current_subframe; for(dci_candidate=0; dci_candidate<num_candidate; ++dci_candidate){ while(!is_dlsf(mac_inst, dci_subframe)){ ++dci_subframe; } dci_node = (available_resource_DL_t *)check_resource_DL(mac_inst, dci_subframe, num_dci_subframe, &dci_end_subframe, &dci_first_subframe); if((available_resource_DL_t *)0 != dci_node){ //dci_subframe += dci_candidate*num_dci_subframe; printf("%d msg4 dci %d - %d\n", mac_inst->current_subframe, dci_first_subframe, dci_end_subframe); break; } res = num_dci_subframe; while(res != 0){ // cost lot of time to search if(is_dlsf(mac_inst, dci_subframe)){ res--; } dci_subframe++; } } if(num_candidate==dci_candidate){ //failed fail|=1; } // check msg4 resource rep = dl_rep[msg4_nodes->ce_level]; num_msg4_subframe = 1*rep; // 8 subframes msg4_i_delay = find_suit_i_delay(rmax, r, dci_candidate); for(i=msg4_i_delay; i<8; ++i){ msg4_i_delay = (msg4_i_delay==8)?0:msg4_i_delay; msg4_subframe = dci_end_subframe+4+get_scheduling_delay(msg4_i_delay, rmax); msg4_node = (available_resource_DL_t *)check_resource_DL(mac_inst, msg4_subframe, num_msg4_subframe*rep, &msg4_end_subframe, &msg4_first_subframe); if((available_resource_DL_t *)0 != msg4_node){ //printf("[MSG4]\t\t\tstart %3d, num %3d, end %3d\n", msg4_subframe, num_msg4_subframe, msg4_end_subframe); printf("%d msg4 %d - %d\n", mac_inst->current_subframe, msg4_first_subframe, msg4_end_subframe); break; } } if(8==i){ //failed fail|=2; } rep = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg4_nodes->ce_level].mac_numRepetitionsPerPreambleAttempt_NB_IoT; //print_available_UL_resource(); for(HARQ_delay=0;HARQ_delay<4;++HARQ_delay){ end_flagHARQ=Check_UL_resource(msg4_end_subframe+get_HARQ_delay(1, HARQ_delay), rep, &HARQ_info, 0, 1); // RA_template->R if(0 == end_flagHARQ){ harq_subframe = msg4_end_subframe + get_HARQ_delay(1, HARQ_delay); harq_end_subframe = harq_subframe + 2*rep -1; HARQ_info.ACK_NACK_resource_field=get_resource_field_value(HARQ_info.subcarrier_indication, get_scheduling_delay(HARQ_delay, rmax)); break; } } if(4 == HARQ_delay){ fail |= 4; } if(0==fail){ //SCHEDULE_LOG("[%04d][RA scheduler][MSG4] rnti: %d preamble: %d success\n", mac_inst->current_subframe, msg4_nodes->ra_rnti, msg4_nodes->preamble_index); msg4_nodes->wait_msg4_ack = 1; DCIFormatN1_t *dci_n1_msg4 = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t)); // dci entity dci_n1_msg4->type = 1; dci_n1_msg4->orderIndicator = 0; dci_n1_msg4->Scheddly = msg4_i_delay; dci_n1_msg4->ResAssign = 0; dci_n1_msg4->mcs = 0; dci_n1_msg4->RepNum = 1; dci_n1_msg4->ndi = 1; dci_n1_msg4->HARQackRes = HARQ_info.ACK_NACK_resource_field; dci_n1_msg4->DCIRep = 1; // for dci dci_result = (schedule_result_t *)malloc(sizeof(schedule_result_t)); dci_result->output_subframe = dci_first_subframe;//dci_subframe; dci_result->end_subframe = dci_end_subframe; dci_result->sdu_length = 0; dci_result->direction = DL; dci_result->DCI_release = 0; dci_result->channel = NPDCCH; dci_result->rnti = msg4_nodes->ue_rnti; dci_result->rnti_type = 1; dci_result->npusch_format = 0; //useless dci_result->R_harq = 0; dci_result->next = (schedule_result_t *)0; dci_result->DCI_pdu = (void *)dci_n1_msg4; // for msg4 msg4_result = (schedule_result_t *)malloc(sizeof(schedule_result_t)); msg4_result->output_subframe = msg4_first_subframe;// msg4_subframe; msg4_result->end_subframe = msg4_end_subframe; msg4_result->sdu_length = 0; msg4_result->direction = DL; msg4_result->DCI_release = 0; msg4_result->channel = NPDSCH; msg4_result->rnti = msg4_nodes->ue_rnti; msg4_result->rnti_type = 1; msg4_result->npusch_format = 0; //useless msg4_result->R_harq = 0; msg4_result->next = (schedule_result_t *)0; msg4_result->DCI_pdu = (void *)dci_n1_msg4; harq_result = (schedule_result_t *)malloc(sizeof(schedule_result_t)); harq_result->rnti = msg4_nodes->ue_rnti; harq_result->output_subframe = harq_subframe; harq_result->end_subframe = harq_end_subframe; harq_result->sdu_length = 0; harq_result->direction = UL; harq_result->rnti_type = 3; harq_result->DLSCH_pdu = NULL; harq_result->DCI_pdu = (void *)dci_n1_msg4; harq_result->DCI_release = 1; harq_result->channel = NPUSCH; harq_result->next = (schedule_result_t *)0; if(msg4_nodes->msg4_retransmit_count==0){ dci_result->debug_str = str3; msg4_result->debug_str = str4; harq_result->debug_str = str5; }else{ dci_result->debug_str = str8; msg4_result->debug_str = str9; harq_result->debug_str = str10; } //simulate_rx(&simulate_rx_msg4_list, msg4_nodes->ue_rnti, harq_subframe); //DEBUG("[%04d][RA scheduler][MSG4] UE:%x MSG4DCI %d-%d MSG4 %d-%d HARQ %d-%d\n", mac_inst->current_subframe, msg4_nodes->ue_rnti, dci_first_subframe, dci_end_subframe, msg4_first_subframe, msg4_end_subframe, HARQ_info.sf_start, HARQ_info.sf_end); msg4_nodes->msg4_retransmit_count++; // fill dci resource fill_resource_DL(mac_inst, dci_node, dci_first_subframe, dci_end_subframe, dci_result); // fill msg4 resource fill_resource_DL(mac_inst, msg4_node, msg4_first_subframe, msg4_end_subframe, msg4_result); // fill ack/nack resource insert_schedule_result(&schedule_result_list_UL, harq_subframe, harq_result); //DEBUG("check point\n"); adjust_UL_resource_list(&HARQ_info); // active ue_list ul/dl UE_list_NB_IoT_t *UE_list = mac_inst->UE_list_spec; for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){ if(UE_list->UE_template_NB_IoT[i].active == 1 && UE_list->UE_template_NB_IoT[i].rnti == msg4_nodes->ue_rnti){ UE_list->UE_template_NB_IoT[i].direction = rand()&1; } } }else{ //DEBUG("[%04d][RA scheduler][MSG4] fail vector %d\n", mac_inst->current_subframe, fail ); //SCHEDULE_LOG("[%04d][RA scheduler][MSG4] rnti: %d preamble: %d fail vector %d\n", mac_inst->current_subframe, msg4_nodes->ra_rnti, msg4_nodes->preamble_index, fail); } } msg4_nodes = msg4_nodes->next; } return ; } void schedule_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){ //uint32_t current_subframe = mac_inst->current_subframe; schedule_msg3_retransimission_NB_IoT(mac_inst); schedule_rar_NB_IoT(mac_inst); schedule_msg4_NB_IoT(mac_inst); return ; }