Files
openairinterface5g/openair1/SCHED/phy_procedures_lte_eNb.c
T

3405 lines
122 KiB
C
Executable File

/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file phy_procedures_lte_eNB.c
* \brief Implementation of eNB procedures from 36.213 LTE specifications
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "MAC_INTERFACE/defs.h"
#include "MAC_INTERFACE/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif
#define DEBUG_PHY_PROC
//#define DEBUG_ULSCH
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/defs.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/from_grlib_softregs.h"
//#ifdef OPENAIR2
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/defs.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
//#endif
//#define DIAG_PHY
#define NS_PER_SLOT 500000
#define PUCCH 1
#define PUCCH1_THRES 25
extern inline unsigned int taus(void);
extern int exit_openair;
extern void do_OFDM_mod(mod_sym_t **txdataF, s32 **txdata, uint32_t frame, u16 next_slot, LTE_DL_FRAME_PARMS *frame_parms);
unsigned char dlsch_input_buffer[2700] __attribute__ ((aligned(16)));
int eNB_sync_buffer0[640*6] __attribute__ ((aligned(16)));
int eNB_sync_buffer1[640*6] __attribute__ ((aligned(16)));
int *eNB_sync_buffer[2] = {eNB_sync_buffer0, eNB_sync_buffer1};
unsigned int max_peak_val;
int max_sect_id, max_sync_pos;
//DCI_ALLOC_t dci_alloc[8];
#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif
#if defined(SMBV) && !defined(EXMIMO)
extern const char smbv_fname[];
extern unsigned short config_frames[4];
extern u8 smbv_frame_cnt;
#endif
#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif
static unsigned char I0_clear = 1;
u8 is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,u8 UE_id,u8 subframe) {
LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking for SR TXOp(sr_ConfigIndex %d)\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->ulsch_eNB[UE_id]->rnti,phy_vars_eNB->frame,subframe,
phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex);
if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 4) { // 5 ms SR period
if ((subframe%5) == phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex)
return(1);
}
else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 14) { // 10 ms SR period
if (subframe==(phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-5))
return(1);
}
else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 34) { // 20 ms SR period
if ((10*(phy_vars_eNB->frame&1)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-15))
return(1);
}
else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 74) { // 40 ms SR period
if ((10*(phy_vars_eNB->frame&3)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-35))
return(1);
}
else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 154) { // 80 ms SR period
if ((10*(phy_vars_eNB->frame&7)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-75))
return(1);
}
return(0);
}
s32 add_ue(s16 rnti, PHY_VARS_eNB *phy_vars_eNB) {
u8 i;
//#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d] Adding UE with rnti %x\n",phy_vars_eNB->Mod_id,rnti);
//#endif
for (i=0;i<NUMBER_OF_UE_MAX;i++) {
if ((phy_vars_eNB->dlsch_eNB[i]==NULL) || (phy_vars_eNB->ulsch_eNB[i]==NULL)) {
LOG_E(PHY,"Can't add UE, not enough memory allocated\n");
return(-1);
}
else {
if (phy_vars_eNB->eNB_UE_stats[i].crnti==0) {
LOG_I(PHY,"UE_id %d associated with rnti %x\n",i, rnti);
phy_vars_eNB->dlsch_eNB[i][0]->rnti = rnti;
phy_vars_eNB->ulsch_eNB[i]->rnti = rnti;
phy_vars_eNB->eNB_UE_stats[i].crnti = rnti;
return(i);
}
}
}
return(-1);
}
s32 remove_ue(u16 rnti, PHY_VARS_eNB *phy_vars_eNB, u8 abstraction_flag) {
u8 i;
//#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"eNB %d removing UE with rnti %x\n",phy_vars_eNB->Mod_id,rnti);
//#endif
for (i=0;i<NUMBER_OF_UE_MAX;i++) {
if ((phy_vars_eNB->dlsch_eNB[i]==NULL) || (phy_vars_eNB->ulsch_eNB[i]==NULL)) {
LOG_E(PHY,"Can't remove UE, not enough memory allocated\n");
return(-1);
}
else {
if (phy_vars_eNB->eNB_UE_stats[i].crnti==rnti) {
//msg("[PHY] UE_id %d\n",i);
clean_eNb_dlsch(phy_vars_eNB->dlsch_eNB[i][0], abstraction_flag);
clean_eNb_ulsch(phy_vars_eNB->ulsch_eNB[i],abstraction_flag);
//phy_vars_eNB->eNB_UE_stats[i].crnti = 0;
memset(&phy_vars_eNB->eNB_UE_stats[i],0,sizeof(LTE_eNB_UE_stats));
return(i);
}
}
}
return(-1);
}
s8 find_next_ue_index(PHY_VARS_eNB *phy_vars_eNB) {
u8 i;
for (i=0;i<NUMBER_OF_UE_MAX;i++) {
if (phy_vars_eNB->eNB_UE_stats[i].crnti==0) {
/*if ((phy_vars_eNB->dlsch_eNB[i]) &&
(phy_vars_eNB->dlsch_eNB[i][0]) &&
(phy_vars_eNB->dlsch_eNB[i][0]->rnti==0))*/
LOG_D(PHY,"Next free UE id is %d\n",i);
return(i);
}
}
return(-1);
}
int get_ue_active_harq_pid(u8 Mod_id,u16 rnti,u8 subframe,u8 *harq_pid,u8 *round,u8 ul_flag) {
LTE_eNB_DLSCH_t *DLSCH_ptr;
LTE_eNB_ULSCH_t *ULSCH_ptr;
// u8 subframe_m4;
u8 ulsch_subframe,ulsch_frame;
u8 i;
s8 UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id]);
u32 frame = PHY_vars_eNB_g[Mod_id]->frame;
if (UE_id==-1) {
LOG_E(PHY,"Cannot find UE with rnti %x\n",rnti);
*round=0;
return(-1);
}
if (ul_flag == 0) {// this is a DL request
DLSCH_ptr = PHY_vars_eNB_g[Mod_id]->dlsch_eNB[(u32)UE_id][0];
/*
if (subframe<4)
subframe_m4 = subframe+6;
else
subframe_m4 = subframe-4;
*/
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] get_ue_active_harq_pid: Frame %d subframe %d, current harq_id %d\n",
Mod_id,frame,subframe,DLSCH_ptr->harq_ids[subframe]);
#endif
// switch on TDD or FDD configuration here later
*harq_pid = DLSCH_ptr->harq_ids[subframe];
if ((*harq_pid<DLSCH_ptr->Mdlharq) &&
((DLSCH_ptr->harq_processes[*harq_pid]->round > 0))) {
*round = DLSCH_ptr->harq_processes[*harq_pid]->round;
LOG_D(PHY,"round %d\n",*round);
// else if ((subframe_m4==5) || (subframe_m4==6)) {
// *harq_pid = 0;//DLSCH_ptr->harq_ids[subframe_m4];//Ankit
// *round = DLSCH_ptr->harq_processes[*harq_pid]->round;
// }
}
else {
// get first free harq_pid (i.e. round 0)
for (i=0;i<DLSCH_ptr->Mdlharq;i++) {
if (DLSCH_ptr->harq_processes[i]!=NULL) {
if (DLSCH_ptr->harq_processes[i]->status != ACTIVE) {
*harq_pid = i;//0;//i; //(Ankit)
*round = 0;
return(0);
}
else {
LOG_D(PHY,"process %d is active\n",i);
}
}
else {
LOG_E(PHY,"[eNB %d] DLSCH process %d for rnti %x (UE_id %d) not allocated\n",Mod_id,i,rnti,UE_id);
return(-1);
}
}
}
}
else { // This is a UL request
ULSCH_ptr = PHY_vars_eNB_g[Mod_id]->ulsch_eNB[(u32)UE_id];
ulsch_subframe = pdcch_alloc2ul_subframe(&PHY_vars_eNB_g[Mod_id]->lte_frame_parms,subframe);
ulsch_frame = pdcch_alloc2ul_frame(&PHY_vars_eNB_g[Mod_id]->lte_frame_parms,frame,subframe);
// Note this is for TDD configuration 3,4,5 only
*harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id]->lte_frame_parms,
ulsch_frame,
ulsch_subframe);
*round = ULSCH_ptr->harq_processes[*harq_pid]->round;
LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Checking HARQ, round %d\n",Mod_id,*harq_pid,frame,subframe,*round);
}
return(0);
}
int CCE_table[800];
void init_nCCE_table(void) {
memset(CCE_table,0,800*sizeof(int));
}
int get_nCCE_offset(unsigned char L, int nCCE, int common_dci, unsigned short rnti, unsigned char subframe) {
int search_space_free,m,nb_candidates,l,i;
unsigned int Yk;
/*
printf("CCE Allocation: ");
for (i=0;i<nCCE;i++)
printf("%d.",CCE_table[i]);
printf("\n");
*/
if (common_dci == 1) {
// check CCE(0 ... L-1)
nb_candidates = (L==4) ? 4 : 2;
for (m = 0 ; m < nb_candidates ; m++) {
search_space_free = 1;
for (l=0;l<L;l++) {
if (CCE_table[(m*L) + l] == 1) {
search_space_free = 0;
break;
}
}
if (search_space_free == 1) {
for (l=0;l<L;l++)
CCE_table[(m*L)+l]=1;
return(m*L);
}
}
return(-1);
}
else { // Find first available in ue specific search space
// according to procedure in Section 9.1.1 of 36.213 (v. 8.6)
// compute Yk
Yk = (unsigned int)rnti;
for (i=0;i<=subframe;i++)
Yk = (Yk*39827)%65537;
Yk = Yk % (nCCE/L);
switch (L) {
case 1:
case 2:
nb_candidates = 6;
break;
case 4:
case 8:
nb_candidates = 2;
break;
}
// LOG_I(PHY,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates);
for (m = 0 ; m < nb_candidates ; m++) {
search_space_free = 1;
for (l=0;l<L;l++) {
if (CCE_table[(((Yk+m)%(nCCE/L))*L) + l] == 1) {
search_space_free = 0;
break;
}
}
if (search_space_free == 1) {
for (l=0;l<L;l++)
CCE_table[(((Yk+m)%(nCCE/L))*L)+l]=1;
return(((Yk+m)%(nCCE/L))*L);
}
}
return(-1);
}
}
#ifdef EMOS
void phy_procedures_emos_eNB_TX(unsigned char next_slot, PHY_VARS_eNB *phy_vars_eNB) {
}
#endif
/*
void phy_procedures_eNB_S_TX(unsigned char next_slot,PHY_VARS_eNB *phy_vars_eNB,u8 abstraction_flag) {
int sect_id = 0, aa;
if (next_slot%2==0) {
#ifdef DEBUG_PHY_PROC
msg("[PHY][eNB %d] Frame %d, slot %d: Generating pilots for DL-S\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot);
#endif
for (sect_id=0;sect_id<number_of_cards;sect_id++) {
if (abstraction_flag == 0) {
for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
#ifdef IFFT_FPGA
memset(&phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id][aa][next_slot*(phy_vars_eNB->lte_frame_parms.N_RB_DL*12)*(phy_vars_eNB->lte_frame_parms.symbols_per_tti>>1)],
0,(phy_vars_eNB->lte_frame_parms.N_RB_DL*12)*(phy_vars_eNB->lte_frame_parms.symbols_per_tti>>1)*sizeof(mod_sym_t));
#else
memset(&phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id][aa][next_slot*phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti>>1)],
0,phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti>>1)*sizeof(mod_sym_t));
#endif
}
generate_pilots_slot(phy_vars_eNB,
phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
next_slot);
msg("[PHY][eNB] Frame %d, subframe %d Generating PSS\n",
phy_vars_eNB->frame,next_slot>>1);
generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
4*AMP,
&phy_vars_eNB->lte_frame_parms,
2,
next_slot);
}
else {
#ifdef PHY_ABSTRACTION
generate_pss_emul(phy_vars_eNB,sect_id);
#endif
}
}
}
}
*/
void phy_procedures_eNB_S_RX(unsigned char last_slot,PHY_VARS_eNB *phy_vars_eNB,u8 abstraction_flag) {
unsigned char sect_id=0;
if (last_slot%2 == 0) {
for (sect_id=0;sect_id<number_of_cards;sect_id++) {
if (abstraction_flag == 0) {
lte_eNB_I0_measurements(phy_vars_eNB,
sect_id,
phy_vars_eNB->first_run_I0_measurements);
}
#ifdef PHY_ABSTRACTION
else {
lte_eNB_I0_measurements_emul(phy_vars_eNB,
sect_id);
}
#endif
}
if (I0_clear == 1)
I0_clear = 0;
}
}
#ifdef EMOS
void phy_procedures_emos_eNB_RX(unsigned char last_slot,PHY_VARS_eNB *phy_vars_eNB) {
u8 aa;
u16 last_subframe_emos;
u16 pilot_pos1 = 3 - phy_vars_eNB->lte_frame_parms.Ncp, pilot_pos2 = 10 - 2*phy_vars_eNB->lte_frame_parms.Ncp;
u32 bytes;
// this is for all UL subframes
/*
if (last_slot > 3)
last_subframe_emos = (last_slot-4)>>1;
else
mac_xface->macphy_exit("should never happen");
*/
last_subframe_emos=0;
#ifdef EMOS_CHANNEL
//if (last_slot%2==1) // this is for all UL subframes
if (last_slot==7)
for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_rx; aa++) {
memcpy(&emos_dump_eNB.channel[aa][last_subframe_emos*2*phy_vars_eNB->lte_frame_parms.N_RB_UL*12],
&phy_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][aa][phy_vars_eNB->lte_frame_parms.N_RB_UL*12*pilot_pos1],
phy_vars_eNB->lte_frame_parms.N_RB_UL*12*sizeof(int));
memcpy(&emos_dump_eNB.channel[aa][(last_subframe_emos*2+1)*phy_vars_eNB->lte_frame_parms.N_RB_UL*12],
&phy_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][aa][phy_vars_eNB->lte_frame_parms.N_RB_UL*12*pilot_pos2],
phy_vars_eNB->lte_frame_parms.N_RB_UL*12*sizeof(int));
}
#endif
if (last_slot==9) {
emos_dump_eNB.timestamp = rt_get_time_ns();
emos_dump_eNB.frame_tx = phy_vars_eNB->frame;
emos_dump_eNB.rx_total_gain_dB = phy_vars_eNB->rx_total_gain_eNB_dB;
emos_dump_eNB.mimo_mode = phy_vars_eNB->transmission_mode[0];
memcpy(&emos_dump_eNB.PHY_measurements_eNB,
&phy_vars_eNB->PHY_measurements_eNB[0],
sizeof(PHY_MEASUREMENTS_eNB));
memcpy(&emos_dump_eNB.eNB_UE_stats[0],&phy_vars_eNB->eNB_UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats));
bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, &emos_dump_eNB, sizeof(fifo_dump_emos_eNB));
//bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, "test", sizeof("test"));
if (bytes!=sizeof(fifo_dump_emos_eNB)) {
LOG_W(PHY,"[eNB %d] Frame %d, slot %d, Problem writing EMOS data to FIFO (bytes=%d, size=%d)\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame, last_slot,bytes,sizeof(fifo_dump_emos_eNB));
}
else {
if (phy_vars_eNB->frame%100==0) {
LOG_D(PHY,"[eNB %d] Frame %d (%d), slot %d, Writing %d bytes EMOS data to FIFO\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame, ((fifo_dump_emos_eNB*)&emos_dump_eNB)->frame_tx, last_slot, bytes);
}
}
}
}
#endif
#ifndef OPENAIR2
void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
int i;
u8 cooperation_flag = phy_vars_eNB->cooperation_flag;
u8 transmission_mode = phy_vars_eNB->transmission_mode[0];
u32 rballoc = 0x00F0;
u32 rballoc2 = 0x000F;
/*
u32 rand = taus();
if ((subframe==8) || (subframe==9) || (subframe==0))
rand = (rand%5)+5;
else
rand = (rand%4)+5;
*/
DCI_pdu->Num_common_dci = 0;
DCI_pdu->Num_ue_spec_dci=0;
switch (subframe) {
/*
case 5:
DCI_pdu->Num_common_dci = 1;
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = SI_RNTI;
DCI_pdu->dci_alloc[0].format = format1A;
DCI_pdu->dci_alloc[0].ra_flag = 0;
BCCH_alloc_pdu.type = 1;
BCCH_alloc_pdu.vrb_type = 0;
BCCH_alloc_pdu.rballoc = computeRIV(25,10,3);
BCCH_alloc_pdu.ndi = 1;
BCCH_alloc_pdu.rv = 1;
BCCH_alloc_pdu.mcs = 1;
BCCH_alloc_pdu.harq_pid = 0;
BCCH_alloc_pdu.TPC = 1; // set to 3 PRB
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],&BCCH_alloc_pdu,sizeof(DCI1A_5MHz_TDD_1_6_t));
break;
*/
case 6:
/*
DCI_pdu->Num_ue_spec_dci = 1;
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI2_5MHz_2A_M10PRB_TDD_t;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0x1236;
DCI_pdu->dci_alloc[0].format = format2_2A_M10PRB;
DCI_pdu->dci_alloc[0].ra_flag = 0;
DLSCH_alloc_pdu1.rballoc = 0x00ff;
DLSCH_alloc_pdu1.TPC = 0;
DLSCH_alloc_pdu1.dai = 0;
DLSCH_alloc_pdu1.harq_pid = 0;
DLSCH_alloc_pdu1.tb_swap = 0;
DLSCH_alloc_pdu1.mcs1 = 0;
DLSCH_alloc_pdu1.ndi1 = 1;
DLSCH_alloc_pdu1.rv1 = 0;
DLSCH_alloc_pdu1.tpmi = 0;
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu1,sizeof(DCI2_5MHz_2A_M10PRB_TDD_t));
*/
break;
case 5:
DCI_pdu->Num_ue_spec_dci = 1;
if (transmission_mode<3) {
//user 1
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_5MHz_TDD_t;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0x1235;
DCI_pdu->dci_alloc[0].format = format1;
DCI_pdu->dci_alloc[0].ra_flag = 0;
DLSCH_alloc_pdu.rballoc = rballoc;
DLSCH_alloc_pdu.TPC = 0;
DLSCH_alloc_pdu.dai = 0;
DLSCH_alloc_pdu.harq_pid = 0;
DLSCH_alloc_pdu.mcs = openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu.ndi = 1;
DLSCH_alloc_pdu.rv = 0;
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu,sizeof(DCI1_5MHz_TDD_t));
//user2
DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI1_5MHz_TDD_t;
DCI_pdu->dci_alloc[1].L = 2;
DCI_pdu->dci_alloc[1].rnti = 0x1236;
DCI_pdu->dci_alloc[1].format = format1;
DCI_pdu->dci_alloc[1].ra_flag = 0;
DLSCH_alloc_pdu.rballoc = rballoc2;
DLSCH_alloc_pdu.TPC = 0;
DLSCH_alloc_pdu.dai = 0;
DLSCH_alloc_pdu.harq_pid = 1;
DLSCH_alloc_pdu.mcs = openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu.ndi = 1;
DLSCH_alloc_pdu.rv = 0;
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu,sizeof(DCI1_5MHz_TDD_t));
}
else if (transmission_mode==5) {
DCI_pdu->Num_ue_spec_dci = 2;
// user 1
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0x1235;
DCI_pdu->dci_alloc[0].format = format1E_2A_M10PRB;
DCI_pdu->dci_alloc[0].ra_flag = 0;
DLSCH_alloc_pdu1E.tpmi = 5; //5=use feedback
DLSCH_alloc_pdu1E.rv = 0;
DLSCH_alloc_pdu1E.ndi = 1;
DLSCH_alloc_pdu1E.mcs = openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu1E.harq_pid = 0;
DLSCH_alloc_pdu1E.dai = 0;
DLSCH_alloc_pdu1E.TPC = 0;
DLSCH_alloc_pdu1E.rballoc = openair_daq_vars.ue_dl_rb_alloc;
DLSCH_alloc_pdu1E.rah = 0;
DLSCH_alloc_pdu1E.dl_power_off = 0; //0=second user present
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
//user 2
DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t;
DCI_pdu->dci_alloc[1].L = 2;
DCI_pdu->dci_alloc[1].rnti = 0x1236;
DCI_pdu->dci_alloc[1].format = format1E_2A_M10PRB;
DCI_pdu->dci_alloc[1].ra_flag = 0;
DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28);
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
// set the precoder of the second UE orthogonal to the first
phy_vars_eNB->eNB_UE_stats[1].DL_pmi_single = (phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single ^ 0x1555);
}
break;
/*
case 8:
DCI_pdu->Num_common_dci = 1;
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0xbeef;
DCI_pdu->dci_alloc[0].format = format1A;
DCI_pdu->dci_alloc[0].ra_flag = 1;
RA_alloc_pdu.type = 1;
RA_alloc_pdu.vrb_type = 0;
RA_alloc_pdu.rballoc = computeRIV(25,12,3);
RA_alloc_pdu.ndi = 1;
RA_alloc_pdu.rv = 1;
RA_alloc_pdu.mcs = 4;
RA_alloc_pdu.harq_pid = 0;
RA_alloc_pdu.TPC = 1;
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],&RA_alloc_pdu,sizeof(DCI1A_5MHz_TDD_1_6_t));
break;
*/
case 9:
DCI_pdu->Num_ue_spec_dci = 1;
//user 1
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI0_5MHz_TDD_1_6_t ;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0x1235;
DCI_pdu->dci_alloc[0].format = format0;
DCI_pdu->dci_alloc[0].ra_flag = 0;
UL_alloc_pdu.type = 0;
UL_alloc_pdu.hopping = 0;
UL_alloc_pdu.rballoc = computeRIV(25,2,openair_daq_vars.ue_ul_nb_rb);
UL_alloc_pdu.mcs = openair_daq_vars.target_ue_ul_mcs;
UL_alloc_pdu.ndi = 1;
UL_alloc_pdu.TPC = 0;
UL_alloc_pdu.cshift = 0;
UL_alloc_pdu.dai = 0;
UL_alloc_pdu.cqi_req = 0;
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD_1_6_t));
//user 2
DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI0_5MHz_TDD_1_6_t ;
DCI_pdu->dci_alloc[1].L = 2;
DCI_pdu->dci_alloc[1].rnti = 0x1236;
DCI_pdu->dci_alloc[1].format = format0;
DCI_pdu->dci_alloc[1].ra_flag = 0;
UL_alloc_pdu.type = 0;
UL_alloc_pdu.hopping = 0;
if (cooperation_flag==0)
UL_alloc_pdu.rballoc = computeRIV(25,2+openair_daq_vars.ue_ul_nb_rb,openair_daq_vars.ue_ul_nb_rb);
else
UL_alloc_pdu.rballoc = computeRIV(25,0,openair_daq_vars.ue_ul_nb_rb);
UL_alloc_pdu.mcs = openair_daq_vars.target_ue_ul_mcs;
UL_alloc_pdu.ndi = 1;
UL_alloc_pdu.TPC = 0;
if ((cooperation_flag==0) || (cooperation_flag==1))
UL_alloc_pdu.cshift = 0;
else
UL_alloc_pdu.cshift = 1;
UL_alloc_pdu.dai = 0;
UL_alloc_pdu.cqi_req = 0;
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD_1_6_t));
break;
default:
break;
}
DCI_pdu->nCCE = 0;
for (i=0;i<DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci;i++) {
DCI_pdu->nCCE += (1<<(DCI_pdu->dci_alloc[i].L));
}
}
#ifdef EMOS
void fill_dci_emos(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
int i;
u8 cooperation_flag = phy_vars_eNB->cooperation_flag;
u8 transmission_mode = phy_vars_eNB->transmission_mode[0];
//u32 rballoc = 0x00F0;
//u32 rballoc2 = 0x000F;
/*
u32 rand = taus();
if ((subframe==8) || (subframe==9) || (subframe==0))
rand = (rand%5)+5;
else
rand = (rand%4)+5;
*/
DCI_pdu->Num_common_dci = 0;
DCI_pdu->Num_ue_spec_dci=0;
switch (subframe) {
case 5:
DCI_pdu->Num_ue_spec_dci = 1;
if (transmission_mode<3) {
//user 1
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_5MHz_TDD_t;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0x1235;
DCI_pdu->dci_alloc[0].format = format1;
DCI_pdu->dci_alloc[0].ra_flag = 0;
DLSCH_alloc_pdu.rballoc = openair_daq_vars.ue_dl_rb_alloc;
DLSCH_alloc_pdu.TPC = 0;
DLSCH_alloc_pdu.dai = 0;
DLSCH_alloc_pdu.harq_pid = 1;
DLSCH_alloc_pdu.mcs = openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu.ndi = 1;
DLSCH_alloc_pdu.rv = 0;
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu,sizeof(DCI1_5MHz_TDD_t));
/*
//user2
DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI1_5MHz_TDD_t;
DCI_pdu->dci_alloc[1].L = 2;
DCI_pdu->dci_alloc[1].rnti = 0x1236;
DCI_pdu->dci_alloc[1].format = format1;
DCI_pdu->dci_alloc[1].ra_flag = 0;
DLSCH_alloc_pdu.rballoc = rballoc2;
DLSCH_alloc_pdu.TPC = 0;
DLSCH_alloc_pdu.dai = 0;
DLSCH_alloc_pdu.harq_pid = 1;
DLSCH_alloc_pdu.mcs = openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu.ndi = 1;
DLSCH_alloc_pdu.rv = 0;
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu,sizeof(DCI1_5MHz_TDD_t));
*/
}
else if (transmission_mode==5) {
DCI_pdu->Num_ue_spec_dci = 2;
// user 1
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0x1235;
DCI_pdu->dci_alloc[0].format = format1E_2A_M10PRB;
DCI_pdu->dci_alloc[0].ra_flag = 0;
DLSCH_alloc_pdu1E.tpmi = 5; //5=use feedback
DLSCH_alloc_pdu1E.rv = 0;
DLSCH_alloc_pdu1E.ndi = 1;
DLSCH_alloc_pdu1E.mcs = openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu1E.harq_pid = 1;
DLSCH_alloc_pdu1E.dai = 0;
DLSCH_alloc_pdu1E.TPC = 0;
DLSCH_alloc_pdu1E.rballoc = openair_daq_vars.ue_dl_rb_alloc;
DLSCH_alloc_pdu1E.rah = 0;
DLSCH_alloc_pdu1E.dl_power_off = 0; //0=second user present
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
//user 2
DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t;
DCI_pdu->dci_alloc[1].L = 2;
DCI_pdu->dci_alloc[1].rnti = 0x1236;
DCI_pdu->dci_alloc[1].format = format1E_2A_M10PRB;
DCI_pdu->dci_alloc[1].ra_flag = 0;
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
// set the precoder of the second UE orthogonal to the first
phy_vars_eNB->eNB_UE_stats[1].DL_pmi_single = (phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single ^ 0x1555);
}
break;
case 7:
DCI_pdu->Num_common_dci = 1;
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0xbeef;
DCI_pdu->dci_alloc[0].format = format1A;
DCI_pdu->dci_alloc[0].ra_flag = 1;
RA_alloc_pdu.type = 1;
RA_alloc_pdu.vrb_type = 0;
RA_alloc_pdu.rballoc = computeRIV(25,12,3);
RA_alloc_pdu.ndi = 1;
RA_alloc_pdu.rv = 1;
RA_alloc_pdu.mcs = 4;
RA_alloc_pdu.harq_pid = 0;
RA_alloc_pdu.TPC = 1;
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],&RA_alloc_pdu,sizeof(DCI1A_5MHz_TDD_1_6_t));
break;
case 9:
DCI_pdu->Num_ue_spec_dci = 1;
//user 1
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI0_5MHz_TDD_1_6_t ;
DCI_pdu->dci_alloc[0].L = 2;
DCI_pdu->dci_alloc[0].rnti = 0x1235;
DCI_pdu->dci_alloc[0].format = format0;
DCI_pdu->dci_alloc[0].ra_flag = 0;
UL_alloc_pdu.type = 0;
UL_alloc_pdu.hopping = 0;
UL_alloc_pdu.rballoc = computeRIV(25,0,openair_daq_vars.ue_ul_nb_rb);
UL_alloc_pdu.mcs = openair_daq_vars.target_ue_ul_mcs;
UL_alloc_pdu.ndi = 1;
UL_alloc_pdu.TPC = 0;
UL_alloc_pdu.cshift = 0;
UL_alloc_pdu.dai = 0;
UL_alloc_pdu.cqi_req = 1;
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD_1_6_t));
/*
//user 2
DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI0_5MHz_TDD_1_6_t ;
DCI_pdu->dci_alloc[1].L = 2;
DCI_pdu->dci_alloc[1].rnti = 0x1236;
DCI_pdu->dci_alloc[1].format = format0;
DCI_pdu->dci_alloc[1].ra_flag = 0;
UL_alloc_pdu.type = 0;
UL_alloc_pdu.hopping = 0;
if (cooperation_flag==0)
UL_alloc_pdu.rballoc = computeRIV(25,2+openair_daq_vars.ue_ul_nb_rb,openair_daq_vars.ue_ul_nb_rb);
else
UL_alloc_pdu.rballoc = computeRIV(25,0,openair_daq_vars.ue_ul_nb_rb);
UL_alloc_pdu.mcs = openair_daq_vars.target_ue_ul_mcs;
UL_alloc_pdu.ndi = 1;
UL_alloc_pdu.TPC = 0;
if ((cooperation_flag==0) || (cooperation_flag==1))
UL_alloc_pdu.cshift = 0;
else
UL_alloc_pdu.cshift = 1;
UL_alloc_pdu.dai = 0;
UL_alloc_pdu.cqi_req = 1;
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD_1_6_t));
*/
break;
default:
break;
}
DCI_pdu->nCCE = 0;
for (i=0;i<DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci;i++) {
DCI_pdu->nCCE += (1<<(DCI_pdu->dci_alloc[i].L));
}
}
#endif //EMOS
#endif //OPENAIR2
#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
#define AMP_OVER_2 (AMP>>1)
int QPSK[4]={AMP_OVER_SQRT2|(AMP_OVER_SQRT2<<16),AMP_OVER_SQRT2|((65536-AMP_OVER_SQRT2)<<16),((65536-AMP_OVER_SQRT2)<<16)|AMP_OVER_SQRT2,((65536-AMP_OVER_SQRT2)<<16)|(65536-AMP_OVER_SQRT2)};
int QPSK2[4]={AMP_OVER_2|(AMP_OVER_2<<16),AMP_OVER_2|((65536-AMP_OVER_2)<<16),((65536-AMP_OVER_2)<<16)|AMP_OVER_2,((65536-AMP_OVER_2)<<16)|(65536-AMP_OVER_2)};
void phy_procedures_eNB_TX(unsigned char next_slot,PHY_VARS_eNB *phy_vars_eNB,u8 abstraction_flag) {
u8 *pbch_pdu=&phy_vars_eNB->pbch_pdu[0];
// unsigned int nb_dci_ue_spec = 0, nb_dci_common = 0;
u16 input_buffer_length, re_allocated=0;
u32 sect_id = 0,i,aa;
u8 harq_pid;
DCI_PDU *DCI_pdu;
u8 *DLSCH_pdu=NULL;
#ifndef OPENAIR2
DCI_PDU DCI_pdu_tmp;
u8 DLSCH_pdu_tmp[768*8];
u8 rar;
#endif
s8 UE_id;
u8 num_pdcch_symbols=0;
s16 crnti;
u16 frame_tx;
// s16 amp;
u8 ul_subframe;
u32 ul_frame;
int re_offset;
uint32_t *txptr;
#ifdef Rel10
MCH_PDU *mch_pdu;
#endif
#if defined(SMBV) && !defined(EXMIMO)
// counts number of allocations in subframe
// there is at least one allocation for PDCCH
u8 smbv_alloc_cnt = 1;
#endif
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,1);
#ifdef OPENAIR2
// Get scheduling info for next subframe during odd slot of previous subframe (next_slot is even)
if (next_slot%2 == 0)
mac_xface->eNB_dlsch_ulsch_scheduler(phy_vars_eNB->Mod_id,0,phy_vars_eNB->frame,next_slot>>1);//,1);
#endif
for (sect_id = 0 ; sect_id < number_of_cards; sect_id++) {
if (abstraction_flag==0) {
if (next_slot%2 == 0) {
for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx_eNB;aa++) {
#ifdef IFFT_FPGA
memset(&phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id][aa][next_slot*(phy_vars_eNB->lte_frame_parms.N_RB_DL*12)*(phy_vars_eNB->lte_frame_parms.symbols_per_tti>>1)],
0,(phy_vars_eNB->lte_frame_parms.N_RB_DL*12)*(phy_vars_eNB->lte_frame_parms.symbols_per_tti)*sizeof(mod_sym_t));
#else
memset(&phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id][aa][next_slot*phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti>>1)],
0,phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti)*sizeof(mod_sym_t));
// fill first symbol of each TX subframe with random QPSK data (overwritten by TX routines later). This guarantees that the first symbol is full power
// in case of transmission mode > 1, this all data is filled by the PDCCH routine (which always assumes that pilots are transmitted on all antenna ports)
if (phy_vars_eNB->lte_frame_parms.mode1_flag==1) {
re_offset = phy_vars_eNB->lte_frame_parms.first_carrier_offset;
txptr = (uint32_t*)&phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id][aa][next_slot*phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti>>1)];
for (i=0;i<phy_vars_eNB->lte_frame_parms.N_RB_DL*6;i++)
txptr[re_offset++] = QPSK[taus()&3];
re_offset=1; //skip DC
for (i=0;i<phy_vars_eNB->lte_frame_parms.N_RB_DL*6;i++)
txptr[re_offset++] = QPSK[taus()&3];
}
#endif
}
}
if (is_pmch_subframe(phy_vars_eNB->frame,next_slot>>1,&phy_vars_eNB->lte_frame_parms)) {
if ((next_slot%2) == 0) {
// This is DL-Cell spec pilots in Control region
generate_pilots_slot(phy_vars_eNB,
phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
next_slot,1);
#ifdef Rel10
// get MCH from MAC
mch_pdu = mac_xface->get_mch_sdu(phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1);
fill_eNB_dlsch_MCH(phy_vars_eNB,mch_pdu->mcs,1,0);
LOG_D(PHY,"[eNB%d][MCH] Frame %d: Got MCH pdu for MBSFN Subframe %d : MCS %d, TBS %d\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1,mch_pdu->mcs,phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3);
// Generate PMCH
generate_mch(phy_vars_eNB,next_slot>>1,(uint8_t*)mch_pdu->payload);
/*for (i=0;i<phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3;i++)
printf("%2x.",(uint8_t)mch_pdu->payload[i]);
printf("\n");*/
#endif
}
}
else {
generate_pilots_slot(phy_vars_eNB,
phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
next_slot,0);
if (next_slot == 0) {
// First half of PSS/SSS (FDD)
if (phy_vars_eNB->lte_frame_parms.frame_type == 0) {
generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
4*AMP,
&phy_vars_eNB->lte_frame_parms,
(phy_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5,
next_slot);
generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
&phy_vars_eNB->lte_frame_parms,
(phy_vars_eNB->lte_frame_parms.Ncp==0) ? 5 : 4,
next_slot);
}
}
}
if (next_slot == 1) {
if ((phy_vars_eNB->frame&3) == 0) {
((u8*) pbch_pdu)[2] = 0;
switch (phy_vars_eNB->lte_frame_parms.N_RB_DL) {
case 6:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0x1f) | (0<<5);
break;
case 15:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0x1f) | (1<<5);
break;
case 25:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0x1f) | (2<<5);
break;
case 50:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0x1f) | (3<<5);
break;
case 75:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0x1f) | (4<<5);
break;
case 100:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0x1f) | (5<<5);
break;
default:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0x1f) | (2<<5);
break;
}
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0xef) |
((phy_vars_eNB->lte_frame_parms.phich_config_common.phich_duration << 4)&0x10);
switch (phy_vars_eNB->lte_frame_parms.phich_config_common.phich_resource) {
case oneSixth:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0xf3) | (0<<2);
break;
case half:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0xf3) | (1<<2);
break;
case one:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0xf3) | (2<<2);
break;
case two:
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0xf3) | (3<<2);
break;
default:
break;
}
((u8*) pbch_pdu)[2] = (((u8*) pbch_pdu)[2]&0xfc) | ((phy_vars_eNB->frame>>8)&0x3);
((u8*) pbch_pdu)[1] = phy_vars_eNB->frame&0xfc;
((u8*) pbch_pdu)[0] = 0;
}
/// First half of SSS (TDD)
if (abstraction_flag==0) {
if (phy_vars_eNB->lte_frame_parms.frame_type == 1) {
generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
&phy_vars_eNB->lte_frame_parms,
(phy_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5,
next_slot);
}
}
frame_tx = (((int) (pbch_pdu[2]&0x3))<<8) + ((int) (pbch_pdu[1]&0xfc)) + phy_vars_eNB->frame%4;
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d, slot %d: Calling generate_pbch, mode1_flag=%d, frame_tx=%d, pdu=%02x%02x%02x\n",
phy_vars_eNB->Mod_id,
phy_vars_eNB->frame,
next_slot,
phy_vars_eNB->lte_frame_parms.mode1_flag,
frame_tx,
((u8*) pbch_pdu)[2],
((u8*) pbch_pdu)[1],
((u8*) pbch_pdu)[0]);
#endif
if (abstraction_flag==0) {
generate_pbch(&phy_vars_eNB->lte_eNB_pbch,
phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
&phy_vars_eNB->lte_frame_parms,
pbch_pdu,
phy_vars_eNB->frame&3);
}
#ifdef PHY_ABSTRACTION
else {
generate_pbch_emul(phy_vars_eNB,pbch_pdu);
}
#endif
}
if (next_slot == 2) {
if (abstraction_flag==0) {
if (phy_vars_eNB->lte_frame_parms.frame_type == 1) {
// printf("Generating PSS (frame %d, subframe %d)\n",phy_vars_eNB->frame,next_slot>>1);
generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
4*AMP,
&phy_vars_eNB->lte_frame_parms,
2,
next_slot);
}
}
}
// Second half of PSS/SSS (FDD)
if (next_slot == 10) {
if (abstraction_flag==0) {
if (phy_vars_eNB->lte_frame_parms.frame_type == 0) {
generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
4*AMP,
&phy_vars_eNB->lte_frame_parms,
(phy_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5,
next_slot);
generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
&phy_vars_eNB->lte_frame_parms,
(phy_vars_eNB->lte_frame_parms.Ncp==0) ? 5 : 4,
next_slot);
}
}
}
// Second-half of SSS (TDD)
if (next_slot == 11) {
if (abstraction_flag==0) {
if (phy_vars_eNB->lte_frame_parms.frame_type == 1) {
generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
&phy_vars_eNB->lte_frame_parms,
(phy_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5,
next_slot);
}
}
}
// Second half of PSS (TDD)
if (next_slot == 12) {
if (abstraction_flag==0) {
if (phy_vars_eNB->lte_frame_parms.frame_type == 1) {
// printf("Generating PSS (frame %d, subframe %d)\n",phy_vars_eNB->frame,next_slot>>1);
generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
4*AMP,
&phy_vars_eNB->lte_frame_parms,
2,
next_slot);
}
}
}
}
//return;
sect_id=0;
if ((next_slot % 2)==0) {
//#ifdef DEBUG_PHY_PROC
// msg("[PHY][eNB %d] UE %d: Mode %s\n",phy_vars_eNB->Mod_id,0,mode_string[phy_vars_eNB->eNB_UE_stats[0].mode]);
//#endif
#if defined(SMBV) && !defined(EXMIMO)
// PBCH takes one allocation
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
if (next_slot==0)
smbv_alloc_cnt++;
}
#endif
#ifdef OPENAIR2
// if there are two users and we want to do cooperation
// if ((phy_vars_eNB->eNB_UE_stats[0].mode == PUSCH) && (phy_vars_eNB->eNB_UE_stats[1].mode == PUSCH))
// mac_xface->eNB_dlsch_ulsch_scheduler(phy_vars_eNB->Mod_id,phy_vars_eNB->cooperation_flag,phy_vars_eNB->frame,next_slot>>1);//,1);
// else
// Parse DCI received from MAC
DCI_pdu = mac_xface->get_dci_sdu(phy_vars_eNB->Mod_id,
phy_vars_eNB->frame,
next_slot>>1);
#else
DCI_pdu = &DCI_pdu_tmp;
/*
if ((phy_vars_eNB->frame%1000 == 0) && (phy_vars_eNB->frame>=500) && (next_slot == 0) && (openair_daq_vars.target_ue_dl_mcs<28)) {
openair_daq_vars.target_ue_dl_mcs++;
msg("[MYEMOS] frame %d, increasing MCS to %d\n",phy_vars_eNB->frame,openair_daq_vars.target_ue_dl_mcs);
}
*/
#ifdef EMOS_CHANNEL
fill_dci_emos(DCI_pdu,next_slot>>1,phy_vars_eNB);
#else
fill_dci(DCI_pdu,next_slot>>1,phy_vars_eNB);
#endif
#endif
// clear existing ulsch dci allocations before applying info from MAC (this is table
ul_subframe = pdcch_alloc2ul_subframe(&phy_vars_eNB->lte_frame_parms,next_slot>>1);
ul_frame = pdcch_alloc2ul_frame(&phy_vars_eNB->lte_frame_parms,phy_vars_eNB->frame,next_slot>>1);
if ((subframe_select(&phy_vars_eNB->lte_frame_parms,ul_subframe)==SF_UL) ||
(phy_vars_eNB->lte_frame_parms.frame_type == 0)) {
harq_pid = subframe2harq_pid(&phy_vars_eNB->lte_frame_parms,ul_frame,ul_subframe);
for (i=0;i<NUMBER_OF_UE_MAX;i++)
if (phy_vars_eNB->ulsch_eNB[i]) {
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->dci_alloc=0;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rar_alloc=0;
}
}
#ifdef EMOS
//emos_dump_eNB.dci_cnt[next_slot>>1] = DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci; //nb_dci_common+nb_dci_ue_spec;
#endif
// clear previous allocation information for all UEs
for (i=0;i<NUMBER_OF_UE_MAX;i++) {
phy_vars_eNB->dlsch_eNB[i][0]->subframe_tx[next_slot>>1] = 0;
}
init_nCCE_table();
num_pdcch_symbols = get_num_pdcch_symbols(DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci,
DCI_pdu->dci_alloc,
&phy_vars_eNB->lte_frame_parms,
next_slot>>1);
DCI_pdu->nCCE = get_nCCE(num_pdcch_symbols,
&phy_vars_eNB->lte_frame_parms,
get_mi(&phy_vars_eNB->lte_frame_parms,next_slot>>1));
LOG_D(PHY,"num_pdcch_symbols %d, nCCE %d\n",num_pdcch_symbols,DCI_pdu->nCCE);
#if defined(SMBV) && !defined(EXMIMO)
// Sets up PDCCH and DCI table
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) {
msg("[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",phy_vars_eNB->frame,next_slot>>1,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
dump_dci(&phy_vars_eNB->lte_frame_parms,&DCI_pdu->dci_alloc[0]);
smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (next_slot>>1),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
}
#endif
for (i=0;i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB] Subframe %d : Doing DCI index %d/%d\n",next_slot>>1,i,DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci);
// dump_dci(&phy_vars_eNB->lte_frame_parms,&DCI_pdu->dci_alloc[i]);
#endif
if (DCI_pdu->dci_alloc[i].rnti == SI_RNTI) {
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] SI generate_eNB_dlsch_params_from_dci\n", phy_vars_eNB->Mod_id);
#endif
generate_eNB_dlsch_params_from_dci(next_slot>>1,
&DCI_pdu->dci_alloc[i].dci_pdu[0],
DCI_pdu->dci_alloc[i].rnti,
DCI_pdu->dci_alloc[i].format,
&phy_vars_eNB->dlsch_eNB_SI,
&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->pdsch_config_dedicated,
SI_RNTI,
0,
P_RNTI,
phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single);
if ((phy_vars_eNB->dlsch_eNB_SI->nCCE[next_slot>>1] = get_nCCE_offset(1<<DCI_pdu->dci_alloc[i].L,
DCI_pdu->nCCE,
1,
SI_RNTI,
next_slot>>1)) == -1) {
LOG_E(PHY,"[eNB %d] Frame %d subframe %d : No available CCE resources for common DCI (SI)!!!\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1);
}
else {
LOG_D(PHY,"[eNB %d] Frame %d subframe %d : CCE resource for common DCI (SI) => %d/%d\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1,
phy_vars_eNB->dlsch_eNB_SI->nCCE[next_slot>>1],DCI_pdu->nCCE);
#if defined(SMBV) && !defined(EXMIMO)
// configure SI DCI
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
msg("[SMBV] Frame %3d, SI in SF %d DCI %d\n",phy_vars_eNB->frame,next_slot>>1,i);
smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (next_slot>>1), "SI", &DCI_pdu->dci_alloc[i], i);
}
#endif
}
DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB_SI->nCCE[next_slot>>1];
}
else if (DCI_pdu->dci_alloc[i].ra_flag == 1) {
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] RA generate_eNB_dlsch_params_from_dci\n", phy_vars_eNB->Mod_id);
#endif
generate_eNB_dlsch_params_from_dci(next_slot>>1,
&DCI_pdu->dci_alloc[i].dci_pdu[0],
DCI_pdu->dci_alloc[i].rnti,
DCI_pdu->dci_alloc[i].format,
&phy_vars_eNB->dlsch_eNB_ra,
&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->pdsch_config_dedicated,
SI_RNTI,
DCI_pdu->dci_alloc[i].rnti,
P_RNTI,
phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single);
if ((phy_vars_eNB->dlsch_eNB_ra->nCCE[next_slot>>1] = get_nCCE_offset(1<<DCI_pdu->dci_alloc[i].L,
DCI_pdu->nCCE,
1,
DCI_pdu->dci_alloc[i].rnti,
next_slot>>1)) == -1) {
LOG_E(PHY,"[eNB %d] Frame %d subframe %d : No available CCE resources for common DCI (RA) !!!\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1);
}
else {
LOG_D(PHY,"[eNB %d] Frame %d subframe %d : CCE resource for common DCI (RA) => %d/%d\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1,
phy_vars_eNB->dlsch_eNB_ra->nCCE[next_slot>>1],DCI_pdu->nCCE);
#if defined(SMBV) && !defined(EXMIMO)
// configure RA DCI
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
msg("[SMBV] Frame %3d, RA in SF %d DCI %d\n",phy_vars_eNB->frame,next_slot>>1,i);
smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (next_slot>>1), "RA", &DCI_pdu->dci_alloc[i], i);
}
#endif
}
DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB_ra->nCCE[next_slot>>1];
}
else if (DCI_pdu->dci_alloc[i].format != format0){ // this is a normal DLSCH allocation
#ifdef OPENAIR2
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB] Searching for RNTI %x\n",DCI_pdu->dci_alloc[i].rnti);
#endif
UE_id = find_ue((s16)DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB);
#else
UE_id = i;
#endif
if (UE_id>=0) {
// dump_dci(&phy_vars_eNB->lte_frame_parms,&DCI_pdu->dci_alloc[i]);
#if defined(SMBV) && !defined(EXMIMO)
// Configure this user
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
msg("[SMBV] Frame %3d, SF %d (SMBV SF %d) Configuring user %d with RNTI %d in TM%d\n",phy_vars_eNB->frame,next_slot>>1,(smbv_frame_cnt*10) + (next_slot>>1),UE_id+1,DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->transmission_mode[(u8)UE_id]);
smbv_configure_user(smbv_fname,UE_id+1,phy_vars_eNB->transmission_mode[(u8)UE_id],DCI_pdu->dci_alloc[i].rnti);
}
#endif
generate_eNB_dlsch_params_from_dci(next_slot>>1,
&DCI_pdu->dci_alloc[i].dci_pdu[0],
DCI_pdu->dci_alloc[i].rnti,
DCI_pdu->dci_alloc[i].format,
phy_vars_eNB->dlsch_eNB[(u8)UE_id],
&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->pdsch_config_dedicated,
SI_RNTI,
0,
P_RNTI,
phy_vars_eNB->eNB_UE_stats[(u8)UE_id].DL_pmi_single);
LOG_D(PHY,"[eNB %d][PDSCH %x/%d] Frame %d subframe %d: Generated dlsch params\n",
phy_vars_eNB->Mod_id,DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->current_harq_pid,phy_vars_eNB->frame,next_slot>>1);
if ((phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->nCCE[next_slot>>1] = get_nCCE_offset(1<<DCI_pdu->dci_alloc[i].L,
DCI_pdu->nCCE,
0,
DCI_pdu->dci_alloc[i].rnti,
next_slot>>1)) == -1) {
LOG_E(PHY,"[eNB %d] Frame %d subframe %d : No available CCE resources for UE spec DCI (PDSCH %x) !!!\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1,DCI_pdu->dci_alloc[i].rnti);
}
else {
LOG_D(PHY,"[eNB %d] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %x) => %d/%d\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1,
DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->nCCE[next_slot>>1],DCI_pdu->nCCE);
#if defined(SMBV) && !defined(EXMIMO)
DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->nCCE[next_slot>>1];
// configure UE-spec DCI
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
msg("[SMBV] Frame %3d, PDSCH in SF %d DCI %d\n",phy_vars_eNB->frame,next_slot>>1,i);
smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (next_slot>>1), UE_id+1, &DCI_pdu->dci_alloc[i], i);
}
#endif
}
DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->nCCE[next_slot>>1];
#ifdef DEBUG_PHY_PROC
//if (phy_vars_eNB->frame%100 == 0)
LOG_I(PHY,"[eNB %d][DCI][PDSCH %x] Frame %d subframe %d UE_id %d Generated DCI format %d, aggregation %d\n",
phy_vars_eNB->Mod_id, DCI_pdu->dci_alloc[i].rnti,
phy_vars_eNB->frame, next_slot>>1,UE_id,
DCI_pdu->dci_alloc[i].format,
1<<DCI_pdu->dci_alloc[i].L);
#endif
}
else {
LOG_D(PHY,"[eNB %d][PDSCH] Frame %d : No UE_id with corresponding rnti %x, dropping DLSCH\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame,(s16)DCI_pdu->dci_alloc[i].rnti);
}
}
}
// Apply physicalConfigDedicated if needed
phy_config_dedicated_eNB_step2(phy_vars_eNB);
for (i=0;i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
if (DCI_pdu->dci_alloc[i].format == format0) { // this is a ULSCH allocation
harq_pid = subframe2harq_pid(&phy_vars_eNB->lte_frame_parms,
pdcch_alloc2ul_frame(&phy_vars_eNB->lte_frame_parms,phy_vars_eNB->frame,next_slot>>1),
pdcch_alloc2ul_subframe(&phy_vars_eNB->lte_frame_parms,next_slot>>1));
if (harq_pid==255) {
LOG_E(PHY,"[eNB %d] Frame %d: Bad harq_pid for ULSCH allocation\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame);
mac_xface->macphy_exit("");
}
#ifdef OPENAIR2
UE_id = find_ue((s16)DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB);
#else
UE_id = i;
#endif
if (UE_id<0) {
LOG_E(PHY,"[eNB %d] Frame %d: Unknown UE_id for rnti %x\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame,(s16)DCI_pdu->dci_alloc[i].rnti);
mac_xface->macphy_exit("");
}
#ifdef DEBUG_PHY_PROC
if (phy_vars_eNB->frame%100 == 0)
LOG_I(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Generated format0 DCI (rnti %x, dci %x) (DCI pos %d/%d), aggregation %d\n",
phy_vars_eNB->Mod_id,
subframe2harq_pid(&phy_vars_eNB->lte_frame_parms,
pdcch_alloc2ul_frame(&phy_vars_eNB->lte_frame_parms,(((next_slot>>1)==0)?1:0)+phy_vars_eNB->frame,next_slot>>1),
pdcch_alloc2ul_subframe(&phy_vars_eNB->lte_frame_parms,next_slot>>1)),
pdcch_alloc2ul_frame(&phy_vars_eNB->lte_frame_parms,(((next_slot>>1)==0)?1:0)+phy_vars_eNB->frame,next_slot>>1),
next_slot>>1,DCI_pdu->dci_alloc[i].rnti,
*(unsigned int *)&DCI_pdu->dci_alloc[i].dci_pdu[0],
i,DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci,
1<<DCI_pdu->dci_alloc[i].L);
#endif
//dump_dci(&phy_vars_eNB->lte_frame_parms,&DCI_pdu->dci_alloc[i]);
//LOG_D(PHY,"[eNB] cba generate_eNB_ulsch_params_from_dci for ue %d for dci rnti %x\n", UE_id, DCI_pdu->dci_alloc[i].rnti);
generate_eNB_ulsch_params_from_dci(&DCI_pdu->dci_alloc[i].dci_pdu[0],
DCI_pdu->dci_alloc[i].rnti,
(next_slot>>1),
format0,
UE_id,
phy_vars_eNB,
SI_RNTI,
0,
P_RNTI,
CBA_RNTI,
0); // do_srs
if ((DCI_pdu->dci_alloc[i].nCCE=get_nCCE_offset(1<<DCI_pdu->dci_alloc[i].L,
DCI_pdu->nCCE,
0,
DCI_pdu->dci_alloc[i].rnti,
next_slot>>1)) == -1) {
LOG_E(PHY,"[eNB %d] Frame %d subframe %d : No available CCE resources (%d) for UE spec DCI (PUSCH %x) !!!\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1,DCI_pdu->nCCE,DCI_pdu->dci_alloc[i].rnti);
}
else {
LOG_D(PHY,"[eNB %d] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %x) => %d/%d\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame,next_slot>>1,DCI_pdu->dci_alloc[i].rnti,
DCI_pdu->dci_alloc[i].nCCE,DCI_pdu->nCCE);
#if defined(SMBV) && !defined(EXMIMO)
// configure UE-spec DCI for UL Grant
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
msg("[SMBV] Frame %3d, SF %d UL DCI %d\n",phy_vars_eNB->frame,next_slot>>1,i);
smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (next_slot>>1), UE_id+1, &DCI_pdu->dci_alloc[i], i);
}
#endif
}
/*
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Setting subframe_scheduling_flag for UE %d harq_pid %d (ul subframe %d)\n",
phy_vars_eNB->Mod_id,harq_pid,
phy_vars_eNB->frame,next_slot>>1,i,harq_pid,
pdcch_alloc2ul_subframe(&phy_vars_eNB->lte_frame_parms,next_slot>>1));
#endif
*/
if ((DCI_pdu->dci_alloc[i].rnti >= CBA_RNTI) && (DCI_pdu->dci_alloc[i].rnti < P_RNTI))
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1;
else
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
}
}
// if we have DCI to generate do it now
if ((DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci)>0) {
}
else { // for emulation!!
phy_vars_eNB->num_ue_spec_dci[(next_slot>>1)&1]=0;
phy_vars_eNB->num_common_dci[(next_slot>>1)&1]=0;
}
if (abstraction_flag == 0) {
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %d,ue_spec %d)\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame, next_slot>>1,DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
#endif
for (sect_id=0;sect_id<number_of_cards;sect_id++)
num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_ue_spec_dci,
DCI_pdu->Num_common_dci,
DCI_pdu->dci_alloc,
0,
AMP,
&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
next_slot>>1);
}
#ifdef PHY_ABSTRACTION
else {
LOG_D(PHY,"[eNB %d] Frame %d, subframe %d: Calling generate_dci_top_emul\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame, next_slot>>1);
num_pdcch_symbols = generate_dci_top_emul(phy_vars_eNB,DCI_pdu->Num_ue_spec_dci,DCI_pdu->Num_common_dci,DCI_pdu->dci_alloc,next_slot>>1);
}
#endif
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d, slot %d: num_pdcch_symbols=%d\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame, next_slot,num_pdcch_symbols);
#endif
// Check for SI activity
if (phy_vars_eNB->dlsch_eNB_SI->active == 1) {
input_buffer_length = phy_vars_eNB->dlsch_eNB_SI->harq_processes[0]->TBS/8;
#ifdef OPENAIR2
DLSCH_pdu = mac_xface->get_dlsch_sdu(phy_vars_eNB->Mod_id,
phy_vars_eNB->frame,
SI_RNTI,
0);
#else
DLSCH_pdu = DLSCH_pdu_tmp;
for (i=0;i<input_buffer_length;i++)
DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
#endif
#if defined(SMBV) && !defined(EXMIMO)
// Configures the data source of allocation (allocation is configured by DCI)
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
msg("[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %d\n",phy_vars_eNB->frame,(smbv_frame_cnt*10) + (next_slot>>1),smbv_alloc_cnt);
smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (next_slot>>1), DLSCH_pdu, input_buffer_length);
}
#endif
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
LOG_D(PHY,"[eNB %d][SI] Frame %d, slot %d: Calling generate_dlsch (SI) with input size = %d, num_pdcch_symbols %d\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame, next_slot, input_buffer_length,num_pdcch_symbols);
for (i=0;i<input_buffer_length;i++)
LOG_T(PHY,"%x.",i,DLSCH_pdu[i]);
LOG_T(PHY,"\n");
#endif
#endif
if (abstraction_flag == 0) {
dlsch_encoding(DLSCH_pdu,
&phy_vars_eNB->lte_frame_parms,
num_pdcch_symbols,
phy_vars_eNB->dlsch_eNB_SI,
phy_vars_eNB->frame,next_slot>>1,
&phy_vars_eNB->dlsch_rate_matching_stats,
&phy_vars_eNB->dlsch_turbo_encoding_stats,
&phy_vars_eNB->dlsch_interleaving_stats);
dlsch_scrambling(&phy_vars_eNB->lte_frame_parms,
0,
phy_vars_eNB->dlsch_eNB_SI,
get_G(&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->dlsch_eNB_SI->nb_rb,
phy_vars_eNB->dlsch_eNB_SI->rb_alloc,
get_Qm(phy_vars_eNB->dlsch_eNB_SI->harq_processes[0]->mcs),
num_pdcch_symbols,phy_vars_eNB->frame,next_slot>>1),
0,
next_slot);
for (sect_id=0;sect_id<number_of_cards;sect_id++)
re_allocated = dlsch_modulation(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
next_slot/2,
&phy_vars_eNB->lte_frame_parms,
num_pdcch_symbols,
phy_vars_eNB->dlsch_eNB_SI);
}
#ifdef PHY_ABSTRACTION
else {
dlsch_encoding_emul(phy_vars_eNB,
DLSCH_pdu,
phy_vars_eNB->dlsch_eNB_SI);
}
#endif
phy_vars_eNB->dlsch_eNB_SI->active = 0;
}
// Check for RA activity
if (phy_vars_eNB->dlsch_eNB_ra->active == 1) {
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][RAPROC] Frame %d, slot %d, RA active, filling RAR:\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame, next_slot);
#endif
input_buffer_length = phy_vars_eNB->dlsch_eNB_ra->harq_processes[0]->TBS/8;
#ifdef OPENAIR2
crnti = mac_xface->fill_rar(phy_vars_eNB->Mod_id,
phy_vars_eNB->frame,
dlsch_input_buffer,
phy_vars_eNB->lte_frame_parms.N_RB_UL,
input_buffer_length);
/*
for (i=0;i<input_buffer_length;i++)
LOG_T(PHY,"%x.",dlsch_input_buffer[i]);
LOG_T(PHY,"\n");
*/
UE_id = add_ue(crnti,phy_vars_eNB);
if (UE_id==-1) {
LOG_W(PHY,"[eNB] Max user count reached.\n");
//mac_xface->macphy_exit("[PHY][eNB] Max user count reached.\n");
mac_xface->cancel_ra_proc(phy_vars_eNB->Mod_id,
phy_vars_eNB->frame,
crnti);
}
else {
phy_vars_eNB->eNB_UE_stats[(u32)UE_id].mode = RA_RESPONSE;
// Initialize indicator for first SR (to be cleared after ConnectionSetup is acknowledged)
phy_vars_eNB->first_sr[(u32)UE_id] = 1;
generate_eNB_ulsch_params_from_rar(dlsch_input_buffer,
phy_vars_eNB->frame,
(next_slot>>1),
phy_vars_eNB->ulsch_eNB[(u32)UE_id],
&phy_vars_eNB->lte_frame_parms);
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_active = 1;
get_Msg3_alloc(&phy_vars_eNB->lte_frame_parms,
next_slot>>1,
phy_vars_eNB->frame,
&phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_frame,
&phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_subframe);
#else
for (i=0;i<input_buffer_length;i++)
dlsch_input_buffer[i]= (unsigned char) i; //(taus()&0xff);
dlsch_input_buffer[1] = (phy_vars_eNB->eNB_UE_stats[0].UE_timing_offset)>>(2+4); // 7 MSBs of timing advance + divide by 4
dlsch_input_buffer[2] = ((phy_vars_eNB->eNB_UE_stats[0].UE_timing_offset)<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4
//LOG_I(PHY,"UE %d: timing_offset = %d\n",UE_id,phy_vars_eNB->eNB_UE_stats[0].UE_timing_offset);
#endif
#if defined(SMBV) && !defined(EXMIMO)
// Configures the data source of allocation (allocation is configured by DCI)
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
msg("[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %d\n",phy_vars_eNB->frame,(smbv_frame_cnt*10) + (next_slot>>1),smbv_alloc_cnt);
smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (next_slot>>1), dlsch_input_buffer, input_buffer_length);
}
#endif
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, next slot %d: Calling generate_dlsch (RA) with input size = %d,Msg3 frame %d, Msg3 subframe %d\n",
phy_vars_eNB->Mod_id,
phy_vars_eNB->frame, next_slot,input_buffer_length,
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_frame,
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_subframe);
#endif
if (abstraction_flag == 0) {
dlsch_encoding(dlsch_input_buffer,
&phy_vars_eNB->lte_frame_parms,
num_pdcch_symbols,
phy_vars_eNB->dlsch_eNB_ra,
phy_vars_eNB->frame,next_slot>>1,
&phy_vars_eNB->dlsch_rate_matching_stats,
&phy_vars_eNB->dlsch_turbo_encoding_stats,
&phy_vars_eNB->dlsch_interleaving_stats);
// phy_vars_eNB->dlsch_eNB_ra->rnti = RA_RNTI;
dlsch_scrambling(&phy_vars_eNB->lte_frame_parms,
0,
phy_vars_eNB->dlsch_eNB_ra,
get_G(&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->dlsch_eNB_ra->nb_rb,
phy_vars_eNB->dlsch_eNB_ra->rb_alloc,
get_Qm(phy_vars_eNB->dlsch_eNB_ra->harq_processes[0]->mcs),
num_pdcch_symbols,phy_vars_eNB->frame,next_slot>>1),
0,
next_slot);
for (sect_id=0;sect_id<number_of_cards;sect_id++)
re_allocated = dlsch_modulation(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
next_slot/2,
&phy_vars_eNB->lte_frame_parms,
num_pdcch_symbols,
phy_vars_eNB->dlsch_eNB_ra);
}
#ifdef PHY_ABSTRACTION
else {
dlsch_encoding_emul(phy_vars_eNB,
dlsch_input_buffer,
phy_vars_eNB->dlsch_eNB_ra);
}
#endif
LOG_D(PHY,"[eNB %d][RAPROC] Frame %d subframe %d Deactivating DLSCH RA\n",phy_vars_eNB->Mod_id,
phy_vars_eNB->frame,next_slot>>1);
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d, slot %d, DLSCH (RA) re_allocated = %d\n",phy_vars_eNB->Mod_id,
phy_vars_eNB->frame, next_slot, re_allocated);
#endif
#ifdef OPENAIR2
} //max user count
#endif
phy_vars_eNB->dlsch_eNB_ra->active = 0;
}
// Now scan UE specific DLSCH
for (UE_id=0;UE_id<NUMBER_OF_UE_MAX;UE_id++) {
if ((phy_vars_eNB->dlsch_eNB[(u8)UE_id][0])&&
(phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->rnti>0)&&
(phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->active == 1)) {
harq_pid = phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->current_harq_pid;
input_buffer_length = phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->TBS/8;
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PDSCH %x/%d] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %d, G %d, nb_rb %d, mcs %d, pmi_alloc %x, Ndi %d, rv %d (round %d)\n",
phy_vars_eNB->Mod_id, phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->rnti,harq_pid,
phy_vars_eNB->frame, next_slot>>1, input_buffer_length,
get_G(&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->nb_rb,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->rb_alloc,
get_Qm(phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->mcs),
num_pdcch_symbols,phy_vars_eNB->frame,next_slot>>1),
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->nb_rb,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->mcs,
pmi2hex_2Ar1(phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->pmi_alloc),
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->Ndi,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->rvidx,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->round);
#endif
phy_vars_eNB->eNB_UE_stats[(u8)UE_id].dlsch_sliding_cnt++;
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->harq_processes[harq_pid]->Ndi == 1) {
phy_vars_eNB->eNB_UE_stats[(u32)UE_id].dlsch_trials[0]++;
#ifdef OPENAIR2
DLSCH_pdu = mac_xface->get_dlsch_sdu(phy_vars_eNB->Mod_id,
phy_vars_eNB->frame,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->rnti,
0);
phy_vars_eNB->eNB_UE_stats[UE_id].total_TBS_MAC += phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->TBS;
#else
DLSCH_pdu = DLSCH_pdu_tmp;
for (i=0;i<input_buffer_length;i++)
DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
#endif
#if defined(SMBV) && !defined(EXMIMO)
// Configures the data source of allocation (allocation is configured by DCI)
if (smbv_is_config_frame(phy_vars_eNB->frame) && (smbv_frame_cnt < 4)) {
msg("[SMBV] Frame %3d, Configuring PDSCH payload in SF %d alloc %d\n",phy_vars_eNB->frame,(smbv_frame_cnt*10) + (next_slot>>1),smbv_alloc_cnt);
smbv_configure_datalist_for_user(smbv_fname, UE_id+1, DLSCH_pdu, input_buffer_length);
}
#endif
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
LOG_T(PHY,"eNB DLSCH SDU: \n");
for (i=0;i<phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->TBS>>3;i++)
LOG_T(PHY,"%x.",(u8)DLSCH_pdu[i]);
LOG_T(PHY,"\n");
#endif
#endif
}
else {
phy_vars_eNB->eNB_UE_stats[(u32)UE_id].dlsch_trials[phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->round]++;
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
#endif
#endif
}
if (abstraction_flag==0) {
// 36-212
dlsch_encoding(DLSCH_pdu,
&phy_vars_eNB->lte_frame_parms,
num_pdcch_symbols,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0],
phy_vars_eNB->frame,next_slot>>1,
&phy_vars_eNB->dlsch_rate_matching_stats,
&phy_vars_eNB->dlsch_turbo_encoding_stats,
&phy_vars_eNB->dlsch_interleaving_stats);
// 36-211
dlsch_scrambling(&phy_vars_eNB->lte_frame_parms,
0,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0],
get_G(&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->nb_rb,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->rb_alloc,
get_Qm(phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->mcs),
num_pdcch_symbols,phy_vars_eNB->frame,next_slot>>1),
0,
next_slot);
for (sect_id=0;sect_id<number_of_cards;sect_id++) {
/* if ((phy_vars_eNB->transmission_mode[(u8)UE_id] == 5) &&
(phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->dl_power_off == 0))
amp = (s16)(((s32)AMP*(s32)ONE_OVER_SQRT2_Q15)>>15);
else*/
// amp = AMP;
// if (UE_id == 1)
// LOG_I(PHY,"[MYEMOS] MCS_i %d\n", phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[harq_pid]->mcs);
re_allocated = dlsch_modulation(phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id],
AMP,
next_slot/2,
&phy_vars_eNB->lte_frame_parms,
num_pdcch_symbols,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]);
}
}
#ifdef PHY_ABSTRACTION
else {
dlsch_encoding_emul(phy_vars_eNB,
DLSCH_pdu,
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]);
}
#endif
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->active = 0;
//mac_xface->macphy_exit("first dlsch transmitted\n");
}
else if ((phy_vars_eNB->dlsch_eNB[(u8)UE_id][0])&&
(phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->rnti>0)&&
(phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->active == 0)) {
// clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->subframe_tx[next_slot>>1]=0;
#ifdef DEBUG_PHY_PROC
//LOG_D(PHY,"[eNB %d] DCI: Clearing subframe_tx for subframe %d, UE %d\n",phy_vars_eNB->Mod_id,next_slot>>1,UE_id);
#endif
}
}
// if we have PHICH to generate
// printf("[PHY][eNB] Frame %d subframe %d Checking for phich\n",phy_vars_eNB->frame,next_slot>>1);
if (is_phich_subframe(&phy_vars_eNB->lte_frame_parms,next_slot>>1)) {
#ifdef DEBUG_PHY_PROC
// LOG_D(PHY,"[eNB %d] Frame %d, subframe %d: Calling generate_phich_top\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame, next_slot>>1);
#endif
for (sect_id=0;sect_id<number_of_cards;sect_id++) {
generate_phich_top(phy_vars_eNB,
next_slot>>1,
AMP,
sect_id,
abstraction_flag);
}
}
}
#ifdef EMOS
phy_procedures_emos_eNB_TX(next_slot, phy_vars_eNB);
#endif
}
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,0);
}
void process_Msg3(PHY_VARS_eNB *phy_vars_eNB,u8 last_slot,u8 UE_id, u8 harq_pid) {
// this prepares the demodulation of the first PUSCH of a new user, containing Msg3
int frame = ((last_slot>>1)>=8 ? -1 : 0) + phy_vars_eNB->frame;
LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d (last_slot %d): process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
phy_vars_eNB->Mod_id,
frame,last_slot>>1,last_slot,
UE_id,phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_active,
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_subframe,
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_frame);
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_flag = 0;
if ((phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_active == 1) &&
((last_slot%2)==1) &&
(phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_subframe == (last_slot>>1)) &&
(phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_frame == frame)) {
// harq_pid = 0;
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_active = 0;
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->Msg3_flag = 1;
phy_vars_eNB->ulsch_eNB[(u32)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag=1;
LOG_D(PHY,"[eNB %d][RAPROC] frame %d, slot %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
phy_vars_eNB->Mod_id,
frame,last_slot,last_slot>>1,UE_id);
}
}
// This function retrieves the harq_pid of the corresponding DLSCH process
// and updates the error statistics of the DLSCH based on the received ACK
// info from UE along with the round index. It also performs the fine-grain
// rate-adaptation based on the error statistics derived from the ACK/NAK process
void process_HARQ_feedback(u8 UE_id,
u8 subframe,
PHY_VARS_eNB *phy_vars_eNB,
u8 pusch_flag,
u8 *pucch_payload,
u8 pucch_sel,
u8 SR_payload) {
u8 dl_harq_pid[8],dlsch_ACK[8],j,dl_subframe;
LTE_eNB_DLSCH_t *dlsch = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0];
LTE_eNB_UE_stats *ue_stats = &phy_vars_eNB->eNB_UE_stats[(u32)UE_id];
LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
u8 subframe_m4,M,m;
int mp;
int all_ACKed=1,nb_alloc=0,nb_ACK=0;
int frame = ((subframe>=8) ? -1 : 0) + phy_vars_eNB->frame;
if (phy_vars_eNB->lte_frame_parms.frame_type == 0){ //FDD
subframe_m4 = (subframe<4) ? subframe+6 : subframe-4;
dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
M=1;
if (pusch_flag == 1)
dlsch_ACK[0] = phy_vars_eNB->ulsch_eNB[(u8)UE_id]->o_ACK[0];
else
dlsch_ACK[0] = pucch_payload[0];
LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d for subframe %d\n",phy_vars_eNB->Mod_id,
frame,dlsch_ACK[0],subframe_m4);
}
else { // TDD Handle M=1,2 cases only
M=ul_ACK_subframe2_M(&phy_vars_eNB->lte_frame_parms,
subframe);
// Now derive ACK information for TDD
if (pusch_flag == 1) { // Do PUSCH ACK/NAK first
// detect missing DAI
//FK: this code is just a guess
//RK: not exactly, yes if scheduled from PHICH (i.e. no DCI format 0)
// otherwise, it depends on how many of the PDSCH in the set are scheduled, we can leave it like this,
// but we have to adapt the code below. For example, if only one out of 2 are scheduled, only 1 bit o_ACK is used
dlsch_ACK[0] = phy_vars_eNB->ulsch_eNB[(u8)UE_id]->o_ACK[0];
dlsch_ACK[1] = phy_vars_eNB->ulsch_eNB[(u8)UE_id]->o_ACK[1];
// printf("UE %d: ACK %d,%d\n",UE_id,dlsch_ACK[0],dlsch_ACK[1]);
}
else { // PUCCH ACK/NAK
if ((SR_payload == 1)&&(pucch_sel!=2)) { // decode Table 7.3 if multiplexing and SR=1
nb_ACK = 0;
if (M == 2) {
if ((pucch_payload[0] == 1) && (pucch_payload[1] == 1)) // b[0],b[1]
nb_ACK = 1;
else if ((pucch_payload[0] == 1) && (pucch_payload[1] == 0))
nb_ACK = 2;
}
else if (M == 3) {
if ((pucch_payload[0] == 1) && (pucch_payload[1] == 1))
nb_ACK = 1;
else if ((pucch_payload[0] == 1) && (pucch_payload[1] == 0))
nb_ACK = 2;
else if ((pucch_payload[0] == 0) && (pucch_payload[1] == 1))
nb_ACK = 3;
}
}
else if (pucch_sel == 2) { // bundling or M=1
// printf("*** (%d,%d)\n",pucch_payload[0],pucch_payload[1]);
dlsch_ACK[0] = pucch_payload[0];
dlsch_ACK[1] = pucch_payload[0];
}
else { // multiplexing with no SR, this is table 10.1
if (M==1)
dlsch_ACK[0] = pucch_payload[0];
else if (M==2) {
if (((pucch_sel == 1) && (pucch_payload[0] == 1) && (pucch_payload[1] == 1)) ||
((pucch_sel == 0) && (pucch_payload[0] == 0) && (pucch_payload[1] == 1)))
dlsch_ACK[0] = 1;
else
dlsch_ACK[0] = 0;
if (((pucch_sel == 1) && (pucch_payload[0] == 1) && (pucch_payload[1] == 1)) ||
((pucch_sel == 1) && (pucch_payload[0] == 0) && (pucch_payload[1] == 0)))
dlsch_ACK[1] = 1;
else
dlsch_ACK[1] = 0;
}
}
}
}
// handle case where positive SR was transmitted with multiplexing
if ((SR_payload == 1)&&(pucch_sel!=2)&&(pusch_flag == 0)) {
nb_alloc = 0;
for (m=0;m<M;m++) {
dl_subframe = ul_ACK_subframe2_dl_subframe(&phy_vars_eNB->lte_frame_parms,
subframe,
m);
if (dlsch->subframe_tx[dl_subframe]==1)
nb_alloc++;
}
if (nb_alloc == nb_ACK)
all_ACKed = 1;
else
all_ACKed = 0;
// printf("nb_alloc %d, all_ACKed %d\n",nb_alloc,all_ACKed);
}
for (m=0,mp=-1;m<M;m++) {
dl_subframe = ul_ACK_subframe2_dl_subframe(&phy_vars_eNB->lte_frame_parms,
subframe,
m);
if (dlsch->subframe_tx[dl_subframe]==1) {
if (pusch_flag == 1)
mp++;
else
mp = m;
dl_harq_pid[m] = dlsch->harq_ids[dl_subframe];
if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
if ((SR_payload == 1)&&(all_ACKed == 1))
dlsch_ACK[m] = 1;
else
dlsch_ACK[m] = 0;
}
if (dl_harq_pid[m]<dlsch->Mdlharq) {
dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",phy_vars_eNB->Mod_id,
dlsch->rnti,dl_harq_pid[m],dl_subframe,
dlsch_harq_proc->status,dlsch_harq_proc->round,
dlsch->harq_processes[dl_harq_pid[m]]->mcs,
dlsch->harq_processes[dl_harq_pid[m]]->rvidx,
dlsch->harq_processes[dl_harq_pid[m]]->TBS);
if (dlsch_harq_proc->status==DISABLED)
LOG_E(PHY,"dlsch_harq_proc is disabled? \n");
#endif
if ((dl_harq_pid[m]<dlsch->Mdlharq) &&
(dlsch_harq_proc->status == ACTIVE)) {
// dl_harq_pid of DLSCH is still active
// msg("[PHY] eNB %d Process %d is active (%d)\n",phy_vars_eNB->Mod_id,dl_harq_pid[m],dlsch_ACK[m]);
if ( dlsch_ACK[mp]==0) {
// Received NAK
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PDSCH %x/%d] NAK Received in round %d, requesting retransmission\n",phy_vars_eNB->Mod_id,
dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
#endif
// if (dlsch_harq_proc->round == 0)
ue_stats->dlsch_NAK[dlsch_harq_proc->round]++;
// then Increment DLSCH round index
dlsch_harq_proc->round++;
if (dlsch_harq_proc->round == dlsch->Mdlharq) {
// This was the last round for DLSCH so reset round and increment l2_error counter
#ifdef DEBUG_PHY_PROC
LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",phy_vars_eNB->Mod_id,
dlsch->rnti,dl_harq_pid[m]);
#endif
dlsch_harq_proc->round = 0;
ue_stats->dlsch_l2_errors++;
dlsch_harq_proc->status = SCH_IDLE;
dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq;
}
}
else {
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",phy_vars_eNB->Mod_id,
dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
#endif
ue_stats->dlsch_ACK[dlsch_harq_proc->round]++;
// Received ACK so set round to 0 and set dlsch_harq_pid IDLE
dlsch_harq_proc->round = 0;
dlsch_harq_proc->status = SCH_IDLE;
dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq;
ue_stats->total_TBS = ue_stats->total_TBS +
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
/*
ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
phy_vars_eNB->dlsch_eNB[(u8)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
*/
}
// Do fine-grain rate-adaptation for DLSCH
if (ue_stats->dlsch_NAK[0] > dlsch->error_threshold) {
if (ue_stats->dlsch_mcs_offset == 1)
ue_stats->dlsch_mcs_offset=0;
else
ue_stats->dlsch_mcs_offset=-1;
}
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[process_HARQ_feedback] Frame %d Setting round to %d for pid %d (subframe %d)\n",frame,
dlsch_harq_proc->round,dl_harq_pid[m],subframe);
#endif
// Clear NAK stats and adjust mcs offset
// after measurement window timer expires
if ((ue_stats->dlsch_sliding_cnt == dlsch->ra_window_size) ) {
if ((ue_stats->dlsch_mcs_offset == 0) && (ue_stats->dlsch_NAK[0] < 2))
ue_stats->dlsch_mcs_offset = 1;
if ((ue_stats->dlsch_mcs_offset == 1) && (ue_stats->dlsch_NAK[0] > 2))
ue_stats->dlsch_mcs_offset = 0;
if ((ue_stats->dlsch_mcs_offset == 0) && (ue_stats->dlsch_NAK[0] > 2))
ue_stats->dlsch_mcs_offset = -1;
if ((ue_stats->dlsch_mcs_offset == -1) && (ue_stats->dlsch_NAK[0] < 2))
ue_stats->dlsch_mcs_offset = 0;
for (j=0;j<phy_vars_eNB->dlsch_eNB[j][0]->Mdlharq;j++)
ue_stats->dlsch_NAK[j] = 0;
ue_stats->dlsch_sliding_cnt = 0;
}
}
}
}
}
}
void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB,
u8 UE_id,
u8 subframe,
s16 *n1_pucch0,
s16 *n1_pucch1,
s16 *n1_pucch2,
s16 *n1_pucch3) {
LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->lte_frame_parms;
u8 nCCE0,nCCE1;
int sf;
int frame = ((subframe>=8) ? -1 : 0) + phy_vars_eNB->frame;
if (frame_parms->frame_type == FDD ) {
sf = (subframe<4) ? (subframe+6) : (subframe-4);
// printf("n1_pucch_eNB: subframe %d, nCCE %d\n",sf,phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[sf]);
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[sf]>0) {
*n1_pucch0 = frame_parms->pucch_config_common.n1PUCCH_AN + phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[sf];
*n1_pucch1 = -1;
}
else {
*n1_pucch0 = -1;
*n1_pucch1 = -1;
}
}
else {
switch (frame_parms->tdd_config) {
case 1: // DL:S:UL:UL:DL:DL:S:UL:UL:DL
if (subframe == 2) { // ACK subframes 5 and 6
/* if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[6]>0) {
nCCE1 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[6];
*n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch1 = -1;*/
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[5]>0) {
nCCE0 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[5];
*n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch0 = -1;
*n1_pucch1 = -1;
}
else if (subframe == 3) { // ACK subframe 9
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[9]>0) {
nCCE0 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[9];
*n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch0 = -1;
*n1_pucch1 = -1;
}
else if (subframe == 7) { // ACK subframes 0 and 1
//harq_ack[0].nCCE;
//harq_ack[1].nCCE;
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[0]>0) {
nCCE0 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[0];
*n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch0 = -1;
*n1_pucch1 = -1;
}
else if (subframe == 8) { // ACK subframes 4
//harq_ack[4].nCCE;
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[4]>0) {
nCCE0 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[4];
*n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch0 = -1;
*n1_pucch1 = -1;
}
else {
LOG_D(PHY,"[eNB %d] frame %d: phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n",
phy_vars_eNB->Mod_id,
frame,
subframe,frame_parms->tdd_config);
return;
}
break;
case 3: // DL:S:UL:UL:UL:DL:DL:DL:DL:DL
if (subframe == 2) { // ACK subframes 5,6 and 1 (S in frame-2), forget about n-11 for the moment (S-subframe)
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[6]>0) {
nCCE1 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[6];
*n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch1 = -1;
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[5]>0) {
nCCE0 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[5];
*n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch0 = -1;
}
else if (subframe == 3) { // ACK subframes 7 and 8
LOG_D(PHY,"get_n1_pucch_eNB : subframe 3, subframe_tx[7] %d, subframe_tx[8] %d\n",
phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[7],phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[8]);
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[8]>0) {
nCCE1 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[8];
*n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
LOG_D(PHY,"nCCE1 %d, n1_pucch1 %d\n",nCCE1,*n1_pucch1);
}
else
*n1_pucch1 = -1;
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[7]>0) {
nCCE0 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[7];
*n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
LOG_D(PHY,"nCCE0 %d, n1_pucch0 %d\n",nCCE0,*n1_pucch0);
}
else
*n1_pucch0 = -1;
}
else if (subframe == 4) { // ACK subframes 9 and 0
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[0]>0) {
nCCE1 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[0];
*n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch1 = -1;
if (phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->subframe_tx[9]>0) {
nCCE0 = phy_vars_eNB->dlsch_eNB[(u32)UE_id][0]->nCCE[9];
*n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
}
else
*n1_pucch0 = -1;
}
else {
LOG_D(PHY,"[eNB %d] Frame %d: phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n",
phy_vars_eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
return;
}
break;
} // switch tdd_config
// Don't handle the case M>2
*n1_pucch2 = -1;
*n1_pucch3 = -1;
}
}
void prach_procedures(PHY_VARS_eNB *phy_vars_eNB,u8 subframe,u8 abstraction_flag) {
u16 preamble_energy_list[64],preamble_delay_list[64];
u16 preamble_max,preamble_energy_max;
u16 i;
s8 UE_id;
int frame = ((subframe)>=8 ? -1 : 0) + phy_vars_eNB->frame;
memset(&preamble_energy_list[0],0,64*sizeof(u16));
memset(&preamble_delay_list[0],0,64*sizeof(u16));
if (abstraction_flag == 0) {
LOG_I(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",phy_vars_eNB->Mod_id,
frame,subframe,dB_fixed(signal_energy(&phy_vars_eNB->lte_eNB_common_vars.rxdata[0][0][subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti],512)) - phy_vars_eNB->rx_total_gain_eNB_dB);
// LOG_I(PHY,"[eNB %d][RAPROC] PRACH: rootSequenceIndex %d, prach_ConfigIndex %d, zeroCorrelationZoneConfig %d, highSpeedFlag %d, prach_FreqOffset %d\n",phy_vars_eNB->Mod_id,phy_vars_eNB->lte_frame_parms.prach_config_common.rootSequenceIndex,phy_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, phy_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig,phy_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag,phy_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset);
rx_prach(phy_vars_eNB,
subframe,
preamble_energy_list,
preamble_delay_list,
frame,
0);
}
else {
for (UE_id=0;UE_id<NB_UE_INST;UE_id++) {
LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
UE_id,PHY_vars_UE_g[UE_id],PHY_vars_UE_g[UE_id]->generate_prach,
PHY_vars_UE_g[UE_id]->lte_frame_parms.prach_config_common.rootSequenceIndex,
phy_vars_eNB->lte_frame_parms.prach_config_common.rootSequenceIndex,
PHY_vars_UE_g[UE_id]->prach_PreambleIndex);
if ((PHY_vars_UE_g[UE_id]->generate_prach==1) &&
(PHY_vars_UE_g[UE_id]->lte_frame_parms.prach_config_common.rootSequenceIndex ==
phy_vars_eNB->lte_frame_parms.prach_config_common.rootSequenceIndex) ) {
preamble_energy_list[PHY_vars_UE_g[UE_id]->prach_PreambleIndex] = 80;
preamble_delay_list[PHY_vars_UE_g[UE_id]->prach_PreambleIndex] = 5;
}
}
}
preamble_energy_max = preamble_energy_list[0];
preamble_max = 0;
for (i=1;i<64;i++) {
if (preamble_energy_max < preamble_energy_list[i]) {
preamble_energy_max = preamble_energy_list[i];
preamble_max = i;
}
}
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
preamble_max,
preamble_energy_list[preamble_max],
preamble_delay_list[preamble_max]);
#endif
if (preamble_energy_list[preamble_max] > 60) {
UE_id = find_next_ue_index(phy_vars_eNB);
if (UE_id>=0) {
phy_vars_eNB->eNB_UE_stats[(u32)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
//phy_vars_eNb->eNB_UE_stats[(u32)UE_id].mode = PRACH;
phy_vars_eNB->eNB_UE_stats[(u32)UE_id].sector = 0;
LOG_I(PHY,"[eNB %d][RAPROC] Initiating RA procedure with preamble %d, energy %d, delay %d\n",
phy_vars_eNB->Mod_id,
preamble_max,
preamble_energy_max,
preamble_delay_list[preamble_max]);
#ifdef OPENAIR2
mac_xface->initiate_ra_proc(phy_vars_eNB->Mod_id,
frame,
preamble_max,
preamble_delay_list[preamble_max],
0,subframe,0);
#endif
}
else {
LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
phy_vars_eNB->Mod_id,frame, subframe);
}
}
}
void ulsch_decoding_procedures(unsigned char last_slot, unsigned int i, PHY_VARS_eNB *phy_vars_eNB, unsigned char abstraction_flag)
{
LOG_D(PHY,"ulsch_decoding_procedures not yet implemented. should not be called");
}
void phy_procedures_eNB_RX(unsigned char last_slot,PHY_VARS_eNB *phy_vars_eNB,u8 abstraction_flag) {
//RX processing
u32 l, ret,i,j;
u32 sect_id=0;
u32 harq_pid, round;
u8 SR_payload,*pucch_payload=NULL,pucch_payload0[2]={0,0},pucch_payload1[2]={0,0};
s16 n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3;
u8 do_SR=0,pucch_sel;
s16 metric0=0,metric1=0;
ANFBmode_t bundling_flag;
PUCCH_FMT_t format;
u8 nPRS;
// u8 two_ues_connected = 0;
u8 pusch_active = 0;
LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->lte_frame_parms;
int sync_pos;
u16 rnti=0;
u8 access_mode;
int num_active_cba_groups;
int frame = ((last_slot>>1)>=8 ? -1 : 0 )+ phy_vars_eNB->frame;
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1);
if (abstraction_flag == 0) {
remove_7_5_kHz(phy_vars_eNB,last_slot);
}
//#ifdef OPENAIR2
// check if we have to detect PRACH first
if ((last_slot&1)==1){
// printf("Checking PRACH for eNB %d, subframe %d\n",phy_vars_eNB->Mod_id,last_slot>>1);
if (is_prach_subframe(&phy_vars_eNB->lte_frame_parms,frame,last_slot>>1)>0) {
// printf("Running prach procedures\n");
prach_procedures(phy_vars_eNB,last_slot>>1,abstraction_flag);
}
}
//#endif
if (abstraction_flag == 0) {
for (l=0;l<phy_vars_eNB->lte_frame_parms.symbols_per_tti/2;l++) {
for (sect_id=0;sect_id<number_of_cards;sect_id++) {
slot_fep_ul(&phy_vars_eNB->lte_frame_parms,
&phy_vars_eNB->lte_eNB_common_vars,
l,
last_slot,
sect_id,
#ifdef HW_PREFIX_REMOVAL
1
#else
0
#endif
);
}
}
}
sect_id = 0;
/*
for (UE_id=0;UE_id<NUMBER_OF_UE_MAX;UE_id++) {
if ((phy_vars_eNB->eNB_UE_stats[(u32)UE_id].mode>PRACH) && (last_slot%2==1)) {
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] frame %d, slot %d: Doing SRS estimation and measurements for UE_id %d (UE_mode %d)\n",
phy_vars_eNB->Mod_id,
phy_vars_eNB->frame, last_slot,
UE_id,phy_vars_eNB->eNB_UE_stats[(u32)UE_id].mode);
#endif
for (sect_id=0;sect_id<number_of_cards;sect_id++) {
lte_srs_channel_estimation(&phy_vars_eNB->lte_frame_parms,
&phy_vars_eNB->lte_eNB_common_vars,
&phy_vars_eNB->lte_eNB_srs_vars[(u32)UE_id],
&phy_vars_eNB->soundingrs_ul_config_dedicated[(u32)UE_id],
last_slot>>1,
sect_id);
lte_eNB_srs_measurements(phy_vars_eNB,
sect_id,
UE_id,
1);
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] frame %d, slot %d: UE_id %d, sect_id %d: RX RSSI %d (from SRS)\n",
phy_vars_eNB->Mod_id,
phy_vars_eNB->frame, last_slot,
UE_id,sect_id,
phy_vars_eNB->PHY_measurements_eNB[sect_id].rx_rssi_dBm[(u32)UE_id]);
#endif
}
sect_id=0;
#ifdef USER_MODE
//write_output("srs_est0.m","srsest0",phy_vars_eNB->lte_eNB_common_vars.srs_ch_estimates[0][0],512,1,1);
//write_output("srs_est1.m","srsest1",phy_vars_eNB->lte_eNB_common_vars.srs_ch_estimates[0][1],512,1,1);
#endif
//msg("timing advance in\n");
sync_pos = lte_est_timing_advance(&phy_vars_eNB->lte_frame_parms,
&phy_vars_eNB->lte_eNB_srs_vars[(u32)UE_id],
&sect_id,
phy_vars_eNB->first_run_timing_advance[(u32)UE_id],
number_of_cards,
24576);
//msg("timing advance out\n");
//phy_vars_eNB->eNB_UE_stats[(u32)UE_id].UE_timing_offset = sync_pos - phy_vars_eNB->lte_frame_parms.nb_prefix_samples/8;
phy_vars_eNB->eNB_UE_stats[(u32)UE_id].UE_timing_offset = 0;
phy_vars_eNB->eNB_UE_stats[(u32)UE_id].sector = sect_id;
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] frame %d, slot %d: user %d in sector %d: timing_advance = %d\n",
phy_vars_eNB->Mod_id,
phy_vars_eNB->frame, last_slot,
UE_id, sect_id,
phy_vars_eNB->eNB_UE_stats[(u32)UE_id].UE_timing_offset);
#endif
}
}
else {
}
*/
// Check for active processes in current subframe
harq_pid = subframe2harq_pid(&phy_vars_eNB->lte_frame_parms,
frame,last_slot>>1);
// printf("[eNB][PUSCH] subframe %d => harq_pid %d\n",last_slot>>1,harq_pid);
/*
#ifdef OPENAIR2
if ((phy_vars_eNB->eNB_UE_stats[0].mode == PUSCH) &&
(phy_vars_eNB->eNB_UE_stats[1].mode == PUSCH))
two_ues_connected = 1;
#else
two_ues_connected = 1;
#endif
*/
pusch_active = 0;
// reset the cba flag used for collision detection
for (i=0; i < NUM_MAX_CBA_GROUP; i++){
phy_vars_eNB->cba_last_reception[i]=0;
}
for (i=0;i<NUMBER_OF_UE_MAX;i++) {
/*
if ((i == 1) && (phy_vars_eNB->cooperation_flag > 0) && (two_ues_connected == 1))
break;
*/
#ifdef OPENAIR2
if (phy_vars_eNB->eNB_UE_stats[i].mode == RA_RESPONSE)
process_Msg3(phy_vars_eNB,last_slot,i,harq_pid);
#endif
/*
#ifdef DEBUG_PHY_PROC
if (phy_vars_eNB->ulsch_eNB[i]) {
printf("[PHY][eNB %d][PUSCH %d] frame %d, subframe %d rnti %x, alloc %d\n",phy_vars_eNB->Mod_id,
harq_pid,phy_vars_eNB->frame,last_slot>>1,
(phy_vars_eNB->ulsch_eNB[i]->rnti),
(phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag)
);
}
#endif
*/
if ((phy_vars_eNB->ulsch_eNB[i]) &&
(phy_vars_eNB->ulsch_eNB[i]->rnti>0) &&
(phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1) &&
((last_slot%2)==1)) {
pusch_active = 1;
round = phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round;
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Scheduling PUSCH/ULSCH Reception for rnti %x\n",
phy_vars_eNB->Mod_id,harq_pid,
frame,last_slot>>1,phy_vars_eNB->ulsch_eNB[i]->rnti);
#endif
#ifdef DEBUG_PHY_PROC
if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1){
LOG_D(PHY,"[eNB %d] frame %d, slot %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
phy_vars_eNB->Mod_id,
frame,
last_slot,last_slot>>1,
phy_vars_eNB->eNB_UE_stats[i].sector);
} else {
LOG_D(PHY,"[eNB %d] frame %d, slot %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s sect_id %d\n",
phy_vars_eNB->Mod_id,
frame,
last_slot,last_slot>>1,
i,
mode_string[phy_vars_eNB->eNB_UE_stats[i].mode],
phy_vars_eNB->eNB_UE_stats[i].sector);
}
#endif
nPRS = phy_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[last_slot-1];
phy_vars_eNB->ulsch_eNB[i]->cyclicShift = (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->n_DMRS2 + phy_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + nPRS)%12;
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, Ndi %d, first_rb %d, nb_rb %d, mcs %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, nprs %d), O_ACK %d \n",
phy_vars_eNB->Mod_id,harq_pid,frame,last_slot>>1,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->dci_alloc,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rar_alloc,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->Ndi,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->mcs,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rvidx,
phy_vars_eNB->ulsch_eNB[i]->cyclicShift,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->n_DMRS2,
phy_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
nPRS,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK);
#endif
if (abstraction_flag==0) {
rx_ulsch(phy_vars_eNB,
last_slot>>1,
phy_vars_eNB->eNB_UE_stats[i].sector, // this is the effective sector id
i,
phy_vars_eNB->ulsch_eNB,
0);
}
#ifdef PHY_ABSTRACTION
else {
rx_ulsch_emul(phy_vars_eNB,
last_slot>>1,
phy_vars_eNB->eNB_UE_stats[i].sector, // this is the effective sector id
i);
}
#endif
for (j=0;j<phy_vars_eNB->lte_frame_parms.nb_antennas_rx;j++)
phy_vars_eNB->eNB_UE_stats[i].UL_rssi[j] = dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[j]) - phy_vars_eNB->rx_total_gain_eNB_dB;
if (abstraction_flag == 0) {
ret = ulsch_decoding(phy_vars_eNB,
i,
last_slot>>1,
0, // control_only_flag
0, //Nbundled, to be updated!!!!
0);
}
#ifdef PHY_ABSTRACTION
else {
ret = ulsch_decoding_emul(phy_vars_eNB,
last_slot>>1,
i,
&rnti);
}
#endif
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n",
phy_vars_eNB->Mod_id,harq_pid,
frame,last_slot>>1,
phy_vars_eNB->ulsch_eNB[i]->rnti,
dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]),
dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]),
phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[0],
phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[1],
phy_vars_eNB->ulsch_eNB[i]->o_ACK[0],
phy_vars_eNB->ulsch_eNB[i]->o_ACK[1],
ret);
#endif //DEBUG_PHY_PROC
/*
if ((two_ues_connected==1) && (phy_vars_eNB->cooperation_flag==2)) {
for (j=0;j<phy_vars_eNB->lte_frame_parms.nb_antennas_rx;j++) {
phy_vars_eNB->eNB_UE_stats[i].UL_rssi[j] = dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power_0[j])
- phy_vars_eNB->rx_total_gain_eNB_dB;
phy_vars_eNB->eNB_UE_stats[i+1].UL_rssi[j] = dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power_1[j])
- phy_vars_eNB->rx_total_gain_eNB_dB;
}
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d subframe %d: ULSCH %d RX power UE0 (%d,%d) dB RX power UE1 (%d,%d)\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame,last_slot>>1,i,
dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power_0[0]),
dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power_0[1]),
dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power_1[0]),
dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power_1[1]));
#endif
}
else {
*/
for (j=0;j<phy_vars_eNB->lte_frame_parms.nb_antennas_rx;j++)
phy_vars_eNB->eNB_UE_stats[i].UL_rssi[j] = dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[j])
- phy_vars_eNB->rx_total_gain_eNB_dB;
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d subframe %d: ULSCH %d RX power (%d,%d) dB\n",
phy_vars_eNB->Mod_id,frame,last_slot>>1,i,
dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]),
dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]));
#endif
// }
phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++;
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d Clearing subframe_scheduling_flag\n",
phy_vars_eNB->Mod_id,harq_pid,frame,last_slot>>1,i,harq_pid);
#endif
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
if (phy_vars_eNB->ulsch_eNB[i]->cqi_crc_status == 1) {
#ifdef DEBUG_PHY_PROC
//if (((phy_vars_eNB->frame%10) == 0) || (phy_vars_eNB->frame < 50))
print_CQI(phy_vars_eNB->ulsch_eNB[i]->o,phy_vars_eNB->ulsch_eNB[i]->uci_format,0);
#endif
extract_CQI(phy_vars_eNB->ulsch_eNB[i]->o,phy_vars_eNB->ulsch_eNB[i]->uci_format,&phy_vars_eNB->eNB_UE_stats[i], &rnti, &access_mode);
phy_vars_eNB->eNB_UE_stats[i].rank = phy_vars_eNB->ulsch_eNB[i]->o_RI[0];
}
if (ret == (1+MAX_TURBO_ITERATIONS)) {
phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[harq_pid][phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 0;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round++;
LOG_D(PHY,"[UE][PUSCH %d] Increasing to round %d\n",harq_pid,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round);
// dump_ulsch(phy_vars_eNB, last_slot>>1, i);
// exit(-1);
if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) {
LOG_D(PHY,"[eNB %d][RAPROC] frame %d, slot %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
phy_vars_eNB->Mod_id,
frame,last_slot,last_slot>>1, i,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1,
phy_vars_eNB->lte_frame_parms.maxHARQ_Msg3Tx-1);
if (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round ==
phy_vars_eNB->lte_frame_parms.maxHARQ_Msg3Tx) {
LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n",
phy_vars_eNB->Mod_id, i);
phy_vars_eNB->eNB_UE_stats[i].mode = PRACH;
#ifdef OPENAIR2
mac_xface->cancel_ra_proc(phy_vars_eNB->Mod_id,
frame,
phy_vars_eNB->eNB_UE_stats[i].crnti);
#endif
remove_ue(phy_vars_eNB->eNB_UE_stats[i].crnti,phy_vars_eNB,abstraction_flag);
phy_vars_eNB->ulsch_eNB[(u32)i]->Msg3_active = 0;
//phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 0;
}
else {
// activate retransmission for Msg3 (signalled to UE PHY by PHICH (not MAC/DCI)
phy_vars_eNB->ulsch_eNB[(u32)i]->Msg3_active = 1;
get_Msg3_alloc_ret(&phy_vars_eNB->lte_frame_parms,
last_slot>>1,
frame,
&phy_vars_eNB->ulsch_eNB[i]->Msg3_frame,
&phy_vars_eNB->ulsch_eNB[i]->Msg3_subframe);
}
} // This is Msg3 error
else { //normal ULSCH
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n",
phy_vars_eNB->Mod_id,harq_pid,
frame,last_slot>>1, i,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1,
phy_vars_eNB->ulsch_eNB[i]->Mdlharq,
phy_vars_eNB->ulsch_eNB[i]->o_ACK[0],
phy_vars_eNB->ulsch_eNB[i]->o_ACK[1]);
LOG_I(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:\n",phy_vars_eNB->frame,last_slot>>1,
harq_pid,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3);
for (j=0;j<phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3;j++)
LOG_T(PHY,"%x.",phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->c[0][j]);
LOG_T(PHY,"\n");
//dump_ulsch(phy_vars_eNB, last_slot>>1, i);
if (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round== phy_vars_eNB->ulsch_eNB[i]->Mdlharq) {
LOG_I(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mdlharq %d reached\n",
phy_vars_eNB->Mod_id,harq_pid,
frame,last_slot>>1, i,
phy_vars_eNB->ulsch_eNB[i]->Mdlharq);
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round=0;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active=0;
phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[harq_pid]++;
phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors[harq_pid]++;
//dump_ulsch(phy_vars_eNB, last_slot>>1, i);
//mac_xface->macphy_exit("");
}
// If we've dropped the UE, go back to PRACH mode for this UE
if (phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors[harq_pid] == 20) {
LOG_I(PHY,"[eNB %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached, removing UE\n",
phy_vars_eNB->Mod_id,frame,last_slot>>1, i);
phy_vars_eNB->eNB_UE_stats[i].mode = PRACH;
#ifdef OPENAIR2
mac_xface->cancel_ra_proc(phy_vars_eNB->Mod_id,
frame,
phy_vars_eNB->eNB_UE_stats[i].crnti);
#endif
remove_ue(phy_vars_eNB->eNB_UE_stats[i].crnti,phy_vars_eNB,abstraction_flag);
phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors[harq_pid]=0;
}
}
} // ulsch in error
else {
LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
phy_vars_eNB->Mod_id,harq_pid,
frame,last_slot>>1);
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 1;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0;
phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors[harq_pid] = 0;
if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) {
#ifdef OPENAIR2
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
phy_vars_eNB->Mod_id,
frame,harq_pid,i);
#endif
mac_xface->terminate_ra_proc(phy_vars_eNB->Mod_id,
frame,
phy_vars_eNB->ulsch_eNB[i]->rnti,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3);
#endif
phy_vars_eNB->eNB_UE_stats[i].mode = PUSCH;
phy_vars_eNB->ulsch_eNB[i]->Msg3_flag = 0;
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",phy_vars_eNB->Mod_id,frame,last_slot>>1,i);
#endif //DEBUG_PHY_PROC
for (j=0;j<phy_vars_eNB->dlsch_eNB[i][0]->Mdlharq;j++) {
phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK[j]=0;
phy_vars_eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0;
}
//mac_xface->macphy_exit("Mode PUSCH. Exiting.\n");
}
else {
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,last_slot>>1,
harq_pid,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3);
for (j=0;j<phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3;j++)
LOG_T(PHY,"%x.",phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b[j]);
LOG_T(PHY,"\n");
#endif
#endif
#ifdef OPENAIR2
// if (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->calibration_flag == 0) {
mac_xface->rx_sdu(phy_vars_eNB->Mod_id,
frame,
phy_vars_eNB->ulsch_eNB[i]->rnti,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3);
//}
/*
else {
// Retrieve calibration information and do whatever
LOG_D(PHY,"[eNB][Auto-Calibration] Frame %d, Subframe %d : ULSCH PDU (RX) %d bytes\n",phy_vars_eNB->frame,last_slot>>1,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3);
}
*/
#endif
}
// estimate timing advance for MAC
if (abstraction_flag == 0) {
sync_pos = lte_est_timing_advance_pusch(phy_vars_eNB,i,last_slot>>1);
phy_vars_eNB->eNB_UE_stats[i].timing_advance_update = sync_pos - phy_vars_eNB->lte_frame_parms.nb_prefix_samples/8; //to check
}
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] frame %d, slot %d: user %d in sector %d: timing advance = %d\n",
phy_vars_eNB->Mod_id,
frame, last_slot,
i, sect_id,
phy_vars_eNB->eNB_UE_stats[i].timing_advance_update);
#endif
} // ulsch not in error
// process HARQ feedback
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",phy_vars_eNB->Mod_id,
phy_vars_eNB->dlsch_eNB[i][0]->rnti,
frame,last_slot>>1,
i);
#endif
process_HARQ_feedback(i,
last_slot>>1,
phy_vars_eNB,
1, // pusch_flag
0,
0,
0);
//#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d] Frame %d subframe %d, sect %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n",
phy_vars_eNB->Mod_id,frame,last_slot>>1,
phy_vars_eNB->eNB_UE_stats[i].sector,
harq_pid,
i,
ret,
phy_vars_eNB->ulsch_eNB[i]->cqi_crc_status,
phy_vars_eNB->ulsch_eNB[i]->o_ACK[0],
phy_vars_eNB->ulsch_eNB[i]->o_ACK[1],
phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[harq_pid],
phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][0]);
//#endif
if (frame % 100 == 0) {
if ((phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][round] -
phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_pid][round]) != 0)
phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[harq_pid][round] =
(100*(phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[harq_pid][round] -
phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors_last[harq_pid][round]))/
(phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][round] -
phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_pid][round]);
phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_pid][round] =
phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][round];
phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors_last[harq_pid][round] =
phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[harq_pid][round];
}
}
#ifdef PUCCH
else if ((phy_vars_eNB->dlsch_eNB[i][0]) &&
(phy_vars_eNB->dlsch_eNB[i][0]->rnti>0) &&
((last_slot%2)==1)){ // check for PUCCH
// check SR availability
do_SR = is_SR_subframe(phy_vars_eNB,i,last_slot>>1);
// do_SR = 0;
// Now ACK/NAK
// First check subframe_tx flag for earlier subframes
get_n1_pucch_eNB(phy_vars_eNB,
i,
last_slot>>1,
&n1_pucch0,
&n1_pucch1,
&n1_pucch2,
&n1_pucch3);
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d, subframe %d Checking for PUCCH (%d,%d,%d,%d) SR %d\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->dlsch_eNB[i][0]->rnti,
frame,last_slot>>1,
n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR);
if ((n1_pucch0==-1) && (n1_pucch1==-1) && (do_SR==0)) { // no TX PDSCH that have to be checked and no SR for this UE_id
}
else {
// otherwise we have some PUCCH detection to do
if (do_SR == 1) {
phy_vars_eNB->eNB_UE_stats[i].sr_total++;
if (abstraction_flag == 0)
metric0 = rx_pucch(phy_vars_eNB,
pucch_format1,
i,
phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex,
0, // n2_pucch
1, // shortened format
&SR_payload,
last_slot>>1,
PUCCH1_THRES);
#ifdef PHY_ABSTRACTION
else {
metric0 = rx_pucch_emul(phy_vars_eNB,
i,
pucch_format1,
0,
&SR_payload,
last_slot>>1);
LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",phy_vars_eNB->Mod_id,
phy_vars_eNB->ulsch_eNB[i]->rnti,frame,last_slot>>1,SR_payload,phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex);
}
#endif
if (SR_payload == 1) {
LOG_I(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",phy_vars_eNB->Mod_id,
phy_vars_eNB->ulsch_eNB[i]->rnti,frame,last_slot>>1);
phy_vars_eNB->eNB_UE_stats[i].sr_received++;
if (phy_vars_eNB->first_sr[i] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
phy_vars_eNB->first_sr[i] = 0;
phy_vars_eNB->dlsch_eNB[i][0]->harq_processes[0]->round=0;
phy_vars_eNB->dlsch_eNB[i][0]->harq_processes[0]->status=SCH_IDLE;
LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n",
phy_vars_eNB->Mod_id,
phy_vars_eNB->ulsch_eNB[i]->rnti,frame,last_slot>>1);
}
#ifdef OPENAIR2
mac_xface->SR_indication(phy_vars_eNB->Mod_id,
frame,
phy_vars_eNB->dlsch_eNB[i][0]->rnti,last_slot>>1);
#endif
}
}// do_SR==1
if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR
}
else if (phy_vars_eNB->lte_frame_parms.frame_type==FDD) { // FDD
// if SR was detected, use the n1_pucch from SR, else use n1_pucch0
n1_pucch0 = (SR_payload==1) ? phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex:n1_pucch0;
if (abstraction_flag == 0)
metric0 = rx_pucch(phy_vars_eNB,
pucch_format1a,
i,
(u16)n1_pucch0,
0, //n2_pucch
1, // shortened format
pucch_payload0,
last_slot>>1,
PUCCH1_THRES);
else {
#ifdef PHY_ABSTRACTION
metric0 = rx_pucch_emul(phy_vars_eNB,i,
pucch_format1a,
0,
pucch_payload0,
last_slot>>1);
#endif
}
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
phy_vars_eNB->Mod_id,
phy_vars_eNB->dlsch_eNB[i][0]->rnti,
frame,last_slot>>1,
pucch_payload0[0],metric0);
#endif
process_HARQ_feedback(i,last_slot>>1,phy_vars_eNB,
0,// pusch_flag
pucch_payload0,
2,
SR_payload);
} // FDD
else { //TDD
bundling_flag = phy_vars_eNB->pucch_config_dedicated[i].tdd_AckNackFeedbackMode;
// fix later for 2 TB case and format1b
if ((frame_parms->frame_type==FDD) ||
(bundling_flag==bundling) ||
((frame_parms->frame_type==TDD)&&(frame_parms->tdd_config==1)&&((last_slot!=4)||(last_slot!=14)))) {
format = pucch_format1a;
// msg("PUCCH 1a\n");
}
else {
format = pucch_format1b;
// msg("PUCCH 1b\n");
}
// if SR was detected, use the n1_pucch from SR
if (SR_payload==1) {
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d with SR\n",phy_vars_eNB->Mod_id,
phy_vars_eNB->dlsch_eNB[i][0]->rnti,
frame,last_slot>>1,
n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
#endif
if (abstraction_flag == 0)
metric0 = rx_pucch(phy_vars_eNB,
format,
i,
phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex,
0, //n2_pucch
1, // shortened format
pucch_payload0,
last_slot>>1,
PUCCH1_THRES);
else {
#ifdef PHY_ABSTRACTION
metric0 = rx_pucch_emul(phy_vars_eNB,i,
format,
0,
pucch_payload0,
last_slot>>1);
#endif
}
}
else { //using n1_pucch0/n1_pucch1 resources
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",phy_vars_eNB->Mod_id,
phy_vars_eNB->dlsch_eNB[i][0]->rnti,
frame,last_slot>>1,
n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
#endif
metric0=0;
metric1=0;
// Check n1_pucch0 metric
if (n1_pucch0 != -1) {
if (abstraction_flag == 0)
metric0 = rx_pucch(phy_vars_eNB,
format,
i,
(u16)n1_pucch0,
0, // n2_pucch
1, // shortened format
pucch_payload0,
last_slot>>1,
PUCCH1_THRES);
else {
#ifdef PHY_ABSTRACTION
metric0 = rx_pucch_emul(phy_vars_eNB,i,
format,
0,
pucch_payload0,
last_slot>>1);
#endif
}
}
// Check n1_pucch1 metric
if (n1_pucch1 != -1) {
if (abstraction_flag == 0)
metric1 = rx_pucch(phy_vars_eNB,
format,
i,
(u16)n1_pucch1,
0, //n2_pucch
1, // shortened format
pucch_payload1,
last_slot>>1,
PUCCH1_THRES);
else {
#ifdef PHY_ABSTRACTION
metric1 = rx_pucch_emul(phy_vars_eNB,i,
format,
1,
pucch_payload1,
last_slot>>1);
#endif
}
}
}
if (SR_payload == 1) {
pucch_payload = pucch_payload0;
if (bundling_flag == bundling)
pucch_sel = 2;
}
else if (bundling_flag == multiplexing) { // multiplexing + no SR
pucch_payload = (metric1>metric0) ? pucch_payload1 : pucch_payload0;
pucch_sel = (metric1>metric0) ? 1 : 0;
}
else { // bundling + no SR
if (n1_pucch1 != -1)
pucch_payload = pucch_payload1;
else if (n1_pucch0 != -1)
pucch_payload = pucch_payload0;
pucch_sel = 2; // indicate that this is a bundled ACK/NAK
}
#ifdef DEBUG_PHY_PROC
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, sel %d, (%d,%d)\n",phy_vars_eNB->Mod_id,
phy_vars_eNB->dlsch_eNB[i][0]->rnti,
frame,last_slot>>1,
metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]);
#endif
process_HARQ_feedback(i,last_slot>>1,phy_vars_eNB,
0,// pusch_flag
pucch_payload,
pucch_sel,
SR_payload);
}
}
} // PUCCH processing
#endif //PUCCH
if ((frame % 10 == 0) && (last_slot==9)) {
phy_vars_eNB->eNB_UE_stats[i].dlsch_bitrate = (phy_vars_eNB->eNB_UE_stats[i].total_TBS -
phy_vars_eNB->eNB_UE_stats[i].total_TBS_last)*10;
phy_vars_eNB->eNB_UE_stats[i].total_TBS_last = phy_vars_eNB->eNB_UE_stats[i].total_TBS;
}
num_active_cba_groups = phy_vars_eNB->ulsch_eNB[i]->num_active_cba_groups;
/*if (num_active_cba_groups > 0 )
LOG_D(PHY,"[eNB] last slot %d trying cba transmission decoding UE %d num_grps %d rnti %x flag %d\n",
last_slot, i, num_active_cba_groups,phy_vars_eNB->ulsch_eNB[i]->cba_rnti[i%num_active_cba_groups],
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_cba_scheduling_flag );
*/
if ((phy_vars_eNB->ulsch_eNB[i]) &&
(num_active_cba_groups > 0) &&
(phy_vars_eNB->ulsch_eNB[i]->cba_rnti[i%num_active_cba_groups]>0) &&
(phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_cba_scheduling_flag==1) &&
((last_slot%2)==1)) {
rnti=0;
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Checking PUSCH/ULSCH CBA Reception for UE %d with cba rnti %x mode %s\n",
phy_vars_eNB->Mod_id,harq_pid,
frame,last_slot>>1,
i, (u16)phy_vars_eNB->ulsch_eNB[i]->cba_rnti[i%num_active_cba_groups],mode_string[phy_vars_eNB->eNB_UE_stats[i].mode]);
#endif
if (abstraction_flag==0) {
rx_ulsch(phy_vars_eNB,
last_slot>>1,
phy_vars_eNB->eNB_UE_stats[i].sector, // this is the effective sector id
i,
phy_vars_eNB->ulsch_eNB,
0);
}
#ifdef PHY_ABSTRACTION
else {
rx_ulsch_emul(phy_vars_eNB,
last_slot>>1,
phy_vars_eNB->eNB_UE_stats[i].sector, // this is the effective sector id
i);
}
#endif
if (abstraction_flag == 0) {
ret = ulsch_decoding(phy_vars_eNB,
i,
last_slot>>1,
0, // control_only_flag
0, //Nbundled, to be updated!!!!
0);
}
#ifdef PHY_ABSTRACTION
else {
ret = ulsch_decoding_emul(phy_vars_eNB,
last_slot>>1,
i,
&rnti);
}
#endif
if (phy_vars_eNB->ulsch_eNB[i]->cqi_crc_status == 1) {
#ifdef DEBUG_PHY_PROC
//if (((phy_vars_eNB->frame%10) == 0) || (phy_vars_eNB->frame < 50))
// print_CQI(phy_vars_eNB->ulsch_eNB[i]->o,phy_vars_eNB->ulsch_eNB[i]->uci_format,0);
#endif
extract_CQI(phy_vars_eNB->ulsch_eNB[i]->o,phy_vars_eNB->ulsch_eNB[i]->uci_format,&phy_vars_eNB->eNB_UE_stats[i], &rnti, &access_mode);
phy_vars_eNB->eNB_UE_stats[i].rank = phy_vars_eNB->ulsch_eNB[i]->o_RI[0];
}
/* LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d resetting the subframe_scheduling_flag, total cba groups %d %d\n",
phy_vars_eNB->Mod_id,harq_pid,phy_vars_eNB->frame,last_slot>>1,i,harq_pid,
phy_vars_eNB->ulsch_eNB[i]->num_active_cba_groups,num_active_cba_groups);
*/
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->status= SCH_IDLE;
if ((num_active_cba_groups > 0) &&
// (i % num_active_cba_groups == 0) && // this ue is used a a template for the CBA
(i + num_active_cba_groups < NUMBER_OF_UE_MAX) &&
(phy_vars_eNB->ulsch_eNB[i+num_active_cba_groups]->cba_rnti[i%num_active_cba_groups] > 0 ) &&
(phy_vars_eNB->ulsch_eNB[i+num_active_cba_groups]->num_active_cba_groups> 0)) {
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d resetting the subframe_scheduling_flag for Ue %d cba groups %d members\n",
phy_vars_eNB->Mod_id,harq_pid,frame,last_slot>>1,i,harq_pid,
i+num_active_cba_groups, i%phy_vars_eNB->ulsch_eNB[i]->num_active_cba_groups);
#endif
phy_vars_eNB->ulsch_eNB[i+num_active_cba_groups]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=1;
phy_vars_eNB->ulsch_eNB[i+num_active_cba_groups]->harq_processes[harq_pid]->status= CBA_ACTIVE;
phy_vars_eNB->ulsch_eNB[i+num_active_cba_groups]->harq_processes[harq_pid]->TBS=phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS;
}
if (ret == (1+MAX_TURBO_ITERATIONS)) {
phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[harq_pid][phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 0;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round++;
} // ulsch in error
else {
LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
phy_vars_eNB->Mod_id,harq_pid,
frame,last_slot>>1);
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 1;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0;
phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors[harq_pid] = 0;
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",
frame,last_slot>>1,
harq_pid,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3);
for (j=0;j<phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3;j++)
LOG_T(PHY,"%x.",phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b[j]);
LOG_T(PHY,"\n");
#endif
#endif
if (access_mode > UNKNOWN_ACCESS){
LOG_I(PHY,"[eNB %d] Frame %d, Subframe %d : received ULSCH SDU from CBA transmission, UE (%d,%x), CBA (group %d, rnti %x)\n",
phy_vars_eNB->Mod_id, frame,last_slot>>1,
i, phy_vars_eNB->ulsch_eNB[i]->rnti,
i % phy_vars_eNB->ulsch_eNB[i]->num_active_cba_groups, phy_vars_eNB->ulsch_eNB[i]->cba_rnti[i%num_active_cba_groups]);
// detect if there is a CBA collision
if (phy_vars_eNB->cba_last_reception[i%num_active_cba_groups] == 0 ) {
mac_xface->rx_sdu(phy_vars_eNB->Mod_id,
frame,
phy_vars_eNB->ulsch_eNB[i]->rnti,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b,
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3);
phy_vars_eNB->cba_last_reception[i%num_active_cba_groups]=1;//(last_slot>>1);
} else {
LOG_N(PHY,"[eNB %d] Frame %d subframe %d : CBA collision detected for UE%d for group %d, set the SR for this UE \n ",
phy_vars_eNB->Mod_id,frame,last_slot>>1,
i,i%num_active_cba_groups );
mac_xface->SR_indication(phy_vars_eNB->Mod_id,
frame,
phy_vars_eNB->dlsch_eNB[i][0]->rnti,last_slot>>1);
}
}
} // ULSCH CBA not in error
}
} // loop i=0 ... NUMBER_OF_UE_MAX-1
if (((last_slot&1) == 1 ) &&
(pusch_active == 0)){
if (abstraction_flag == 0) {
// LOG_D(PHY,"[eNB] Frame %d, subframe %d Doing I0_measurements\n",
// (((last_slot>>1)==9)?-1:0) + phy_vars_eNB->frame,last_slot>>1);
lte_eNB_I0_measurements(phy_vars_eNB,
0,
phy_vars_eNB->first_run_I0_measurements);
}
#ifdef PHY_ABSTRACTION
else {
lte_eNB_I0_measurements_emul(phy_vars_eNB,
sect_id);
}
#endif
if (I0_clear == 1)
I0_clear = 0;
}
#ifdef EMOS
phy_procedures_emos_eNB_RX(last_slot,phy_vars_eNB);
#endif
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,0);
}
#undef DEBUG_PHY_PROC
void phy_procedures_eNB_lte(unsigned char last_slot, unsigned char next_slot,PHY_VARS_eNB *phy_vars_eNB,u8 abstraction_flag) {
/*
if (phy_vars_eNB->frame >= 1000)
mac_xface->macphy_exit("Exiting after 1000 Frames\n");
*/
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER, (last_slot + 1) % 20);
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER, phy_vars_eNB->frame);
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,1);
if (((phy_vars_eNB->lte_frame_parms.frame_type == 1)&&(subframe_select(&phy_vars_eNB->lte_frame_parms,next_slot>>1)==SF_DL))||
(phy_vars_eNB->lte_frame_parms.frame_type == 0)){
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d: Calling phy_procedures_eNB_TX(%d)\n", phy_vars_eNB->Mod_id,phy_vars_eNB->frame, next_slot);
#endif
phy_procedures_eNB_TX(next_slot,phy_vars_eNB,abstraction_flag);
}
if (((phy_vars_eNB->lte_frame_parms.frame_type == 1 )&&(subframe_select(&phy_vars_eNB->lte_frame_parms,last_slot>>1)==SF_UL))||
(phy_vars_eNB->lte_frame_parms.frame_type == 0)){
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d: Calling phy_procedures_eNB_RX(%d)\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame, last_slot);
#endif
phy_procedures_eNB_RX(last_slot,phy_vars_eNB,abstraction_flag);
}
if ((subframe_select(&phy_vars_eNB->lte_frame_parms,next_slot>>1)==SF_S) &&
((next_slot&1)==0)) {
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d: Calling phy_procedures_eNB_S_TX(%d)\n",phy_vars_eNB->Mod_id,phy_vars_eNB->frame, next_slot);
#endif
phy_procedures_eNB_TX(next_slot,phy_vars_eNB,abstraction_flag);
}
if ((subframe_select(&phy_vars_eNB->lte_frame_parms,last_slot>>1)==SF_S) &&
((last_slot&1)==0)){
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d: Calling phy_procedures_eNB_S_RX(%d)\n", phy_vars_eNB->Mod_id,phy_vars_eNB->frame, last_slot);
#endif
phy_procedures_eNB_S_RX(last_slot,phy_vars_eNB,abstraction_flag);
}
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,0);
if (next_slot == 19)
phy_vars_eNB->frame++;
}