Commit ad98f5aa authored by Raymond Knopp's avatar Raymond Knopp

L1/L2 scheduling extensions for BL/CE operation, BR random-access procedure,...

L1/L2 scheduling extensions for BL/CE operation, BR random-access procedure, BR PRACH detection. Still untested, but compilation succeeds. Missing elements in L2 - PUSCH programming for Msg3, Msg4 retransmission programming for BL/CE. DLSCH/ULSCH programming for UE-specific DLSCH/ULSCH for BL/CE
parent 1fc67381
This diff is collapsed.
...@@ -43,12 +43,15 @@ const uint8_t lin2alaw_if4p5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 2 ...@@ -43,12 +43,15 @@ const uint8_t lin2alaw_if4p5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 2
void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
int32_t **txdataF = ru->common.txdataF_BF; int32_t **txdataF = ru->common.txdataF_BF;
int32_t **rxdataF = ru->common.rxdataF; int32_t **rxdataF = ru->common.rxdataF;
int16_t **prach_rxsigF = ru->prach_rxsigF; int16_t **prach_rxsigF = ru->prach_rxsigF;
void *tx_buffer = ru->ifbuffer.tx[subframe&1]; #ifdef Rel14
void *tx_buffer_prach = ru->ifbuffer.tx_prach; int16_t ***prach_rxsigF_br = ru->prach_rxsigF_br;
#endif
void *tx_buffer = ru->ifbuffer.tx[subframe&1];
void *tx_buffer_prach = ru->ifbuffer.tx_prach;
uint16_t symbol_id=0, element_id=0; uint16_t symbol_id=0, element_id=0;
...@@ -175,7 +178,8 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { ...@@ -175,7 +178,8 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
perror("ETHERNET write for IF4p5_PULFFT\n"); perror("ETHERNET write for IF4p5_PULFFT\n");
} }
} }
} else if (packet_type == IF4p5_PRACH) { } else if (packet_type >= IF4p5_PRACH &&
packet_type <= IF4p5_PRACH+4) {
// FIX: hard coded prach samples length // FIX: hard coded prach samples length
LOG_D(PHY,"IF4p5_PRACH: frame %d, subframe %d\n",frame,subframe); LOG_D(PHY,"IF4p5_PRACH: frame %d, subframe %d\n",frame,subframe);
db_fulllength = PRACH_NUM_SAMPLES; db_fulllength = PRACH_NUM_SAMPLES;
...@@ -189,13 +193,24 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { ...@@ -189,13 +193,24 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
} }
gen_IF4p5_prach_header(packet_header, frame, subframe); gen_IF4p5_prach_header(packet_header, frame, subframe);
int16_t *rxF;
#ifdef Rel14
if (packet_type > IF4p5_PRACH)
rxF = &prach_rxsigF_br[packet_type - IF4p5_PRACH - 1][0][0];
else
#else
rxF = &prach_rxsigF[0][0];
#endif
if (eth->flags == ETH_RAW_IF4p5_MODE) { if (eth->flags == ETH_RAW_IF4p5_MODE) {
memcpy((int16_t*)(tx_buffer_prach + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t), memcpy((void *)(tx_buffer_prach + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t),
(&prach_rxsigF[0][0]), (void*)rxF,
PRACH_BLOCK_SIZE_BYTES); PRACH_BLOCK_SIZE_BYTES);
} else { } else {
memcpy((int16_t*)(tx_buffer_prach + sizeof_IF4p5_header_t), memcpy((void *)(tx_buffer_prach + sizeof_IF4p5_header_t),
(&prach_rxsigF[0][0]), (void *)rxF,
PRACH_BLOCK_SIZE_BYTES); PRACH_BLOCK_SIZE_BYTES);
} }
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 );
...@@ -204,7 +219,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { ...@@ -204,7 +219,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
&tx_buffer_prach, &tx_buffer_prach,
db_fulllength, db_fulllength,
1, 1,
IF4p5_PRACH)) < 0) { packet_type)) < 0) {
perror("ETHERNET write for IF4p5_PRACH\n"); perror("ETHERNET write for IF4p5_PRACH\n");
} }
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 );
...@@ -217,11 +232,14 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { ...@@ -217,11 +232,14 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
} }
void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint32_t *symbol_number) { void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint32_t *symbol_number) {
LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
int32_t **txdataF = ru->common.txdataF_BF; int32_t **txdataF = ru->common.txdataF_BF;
int32_t **rxdataF = ru->common.rxdataF; int32_t **rxdataF = ru->common.rxdataF;
int16_t **prach_rxsigF = ru->prach_rxsigF; int16_t **prach_rxsigF = ru->prach_rxsigF;
void *rx_buffer = ru->ifbuffer.rx; #ifdef Rel14
int16_t ***prach_rxsigF_br = ru->prach_rxsigF_br;
#endif
void *rx_buffer = ru->ifbuffer.rx;
uint16_t element_id; uint16_t element_id;
uint16_t db_fulllength, db_halflength; uint16_t db_fulllength, db_halflength;
...@@ -308,18 +326,28 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint ...@@ -308,18 +326,28 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint
//if (element_id==0) LOG_I(PHY,"recv_if4p5: symbol %d rxdata0 = (%u,%u)\n",*symbol_number,*i,*(i+1)); //if (element_id==0) LOG_I(PHY,"recv_if4p5: symbol %d rxdata0 = (%u,%u)\n",*symbol_number,*i,*(i+1));
} }
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 );
} else if (*packet_type == IF4p5_PRACH) { } else if (*packet_type >= IF4p5_PRACH &&
*packet_type <= IF4p5_PRACH + 4) {
int16_t *rxF;
#ifdef Rel14
if (*packet_type > IF4p5_PRACH)
rxF = &prach_rxsigF_br[*packet_type - IF4p5_PRACH - 1][0][0];
else
#else
rxF = &prach_rxsigF[0][0];
#endif
// FIX: hard coded prach samples length // FIX: hard coded prach samples length
db_fulllength = PRACH_NUM_SAMPLES; db_fulllength = PRACH_NUM_SAMPLES;
if (eth->flags == ETH_RAW_IF4p5_MODE) { if (eth->flags == ETH_RAW_IF4p5_MODE) {
memcpy((&prach_rxsigF[0][0]), memcpy(rxF,
(int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t), (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t),
PRACH_BLOCK_SIZE_BYTES); PRACH_BLOCK_SIZE_BYTES);
} else { } else {
memcpy((&prach_rxsigF[0][0]), memcpy(rxF,
(int16_t*) (rx_buffer+sizeof_IF4p5_header_t), (int16_t*) (rx_buffer+sizeof_IF4p5_header_t),
PRACH_BLOCK_SIZE_BYTES); PRACH_BLOCK_SIZE_BYTES);
} }
......
...@@ -39,7 +39,11 @@ ...@@ -39,7 +39,11 @@
#define IF4p5_PULFFT 0x0019 #define IF4p5_PULFFT 0x0019
#define IF4p5_PDLFFT 0x0020 #define IF4p5_PDLFFT 0x0020
#define IF4p5_PRACH 0x0021 #define IF4p5_PRACH 0x0021
#define IF4p5_PULTICK 0x0022 #define IF4p5_PRACH_BR_CE0 0x0021
#define IF4p5_PRACH_BR_CE1 0x0022
#define IF4p5_PRACH_BR_CE2 0x0023
#define IF4p5_PRACH_BR_CE3 0x0024
#define IF4p5_PULTICK 0x0025
struct IF4p5_header { struct IF4p5_header {
/// Type /// Type
......
This diff is collapsed.
...@@ -2074,14 +2074,21 @@ int32_t generate_prach(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe, ...@@ -2074,14 +2074,21 @@ int32_t generate_prach(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,
\brief Process PRACH waveform \brief Process PRACH waveform
@param phy_vars_eNB Pointer to eNB top-level descriptor. If NULL, then this is an RRU @param phy_vars_eNB Pointer to eNB top-level descriptor. If NULL, then this is an RRU
@param ru Pointer to RU top-level descriptor. If NULL, then this is an eNB and we make use of the RU_list @param ru Pointer to RU top-level descriptor. If NULL, then this is an eNB and we make use of the RU_list
@param preamble_energy_list List of energies for each candidate preamble @param max_preamble most likely preamble
@param preamble_delay_list List of delays for each candidate preamble @param max_preamble_energy Estimated Energy of most likely preamble
@param max_preamble_delay Estimated Delay of most likely preamble
@param Nf System frame number @param Nf System frame number
@param tdd_mapindex Index of PRACH resource in Table 5.7.1-4 (TDD) @param tdd_mapindex Index of PRACH resource in Table 5.7.1-4 (TDD)
@param br_flag indicator to act on eMTC PRACH
@returns 0 on success @returns 0 on success
*/ */
void rx_prach(PHY_VARS_eNB *phy_vars_eNB,RU_t *ru,uint16_t *preamble_energy_list, uint16_t *preamble_delay_list, uint16_t Nf, uint8_t tdd_mapindex); void rx_prach(PHY_VARS_eNB *phy_vars_eNB,RU_t *ru,
uint16_t *max_preamble,
uint16_t *max_preamble_energy,
uint16_t *max_preamble_delay,
uint16_t Nf, uint8_t tdd_mapindex,
uint8_t br_flag);
/*! /*!
\brief Helper for MAC, returns number of available PRACH in TDD for a particular configuration index \brief Helper for MAC, returns number of available PRACH in TDD for a particular configuration index
...@@ -2169,7 +2176,10 @@ double computeRhoB_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, ...@@ -2169,7 +2176,10 @@ double computeRhoB_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
LTE_UE_DLSCH_t *dlsch_ue); LTE_UE_DLSCH_t *dlsch_ue);
*/ */
uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapindex, uint16_t Nf); uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t prach_ConfigIndex,
uint8_t n_ra_prboffset,
uint8_t tdd_mapindex, uint16_t Nf);
uint8_t ul_subframe2pdcch_alloc_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n); uint8_t ul_subframe2pdcch_alloc_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n);
......
...@@ -288,6 +288,10 @@ typedef struct RU_proc_t_s { ...@@ -288,6 +288,10 @@ typedef struct RU_proc_t_s {
int subframe_tx; int subframe_tx;
/// subframe to act upon for reception of prach /// subframe to act upon for reception of prach
int subframe_prach; int subframe_prach;
#ifdef Rel14
/// subframe to act upon for reception of prach BL/CE UEs
int subframe_prach_br;
#endif
/// frame to act upon for reception /// frame to act upon for reception
int frame_rx; int frame_rx;
/// frame to act upon for transmission /// frame to act upon for transmission
...@@ -296,6 +300,10 @@ typedef struct RU_proc_t_s { ...@@ -296,6 +300,10 @@ typedef struct RU_proc_t_s {
int frame_tx_unwrap; int frame_tx_unwrap;
/// frame to act upon for reception of prach /// frame to act upon for reception of prach
int frame_prach; int frame_prach;
#ifdef Rel14
/// frame to act upon for reception of prach
int frame_prach_br;
#endif
/// frame offset for slave RUs (to correct for frame asynchronism at startup) /// frame offset for slave RUs (to correct for frame asynchronism at startup)
int frame_offset; int frame_offset;
/// \brief Instance count for FH processing thread. /// \brief Instance count for FH processing thread.
...@@ -303,6 +311,10 @@ typedef struct RU_proc_t_s { ...@@ -303,6 +311,10 @@ typedef struct RU_proc_t_s {
int instance_cnt_FH; int instance_cnt_FH;
/// \internal This variable is protected by \ref mutex_prach. /// \internal This variable is protected by \ref mutex_prach.
int instance_cnt_prach; int instance_cnt_prach;
#ifdef Rel14
/// \internal This variable is protected by \ref mutex_prach.
int instance_cnt_prach_br;
#endif
/// \internal This variable is protected by \ref mutex_synch. /// \internal This variable is protected by \ref mutex_synch.
int instance_cnt_synch; int instance_cnt_synch;
/// \internal This variable is protected by \ref mutex_eNBs. /// \internal This variable is protected by \ref mutex_eNBs.
...@@ -316,6 +328,10 @@ typedef struct RU_proc_t_s { ...@@ -316,6 +328,10 @@ typedef struct RU_proc_t_s {
pthread_t pthread_FH; pthread_t pthread_FH;
/// pthread structure for RU prach processing thread /// pthread structure for RU prach processing thread
pthread_t pthread_prach; pthread_t pthread_prach;
#ifdef Rel14
/// pthread structure for RU prach processing thread BL/CE UEs
pthread_t pthread_prach_br;
#endif
/// pthread struct for RU synch thread /// pthread struct for RU synch thread
pthread_t pthread_synch; pthread_t pthread_synch;
/// pthread struct for RU RX FEP thread /// pthread struct for RU RX FEP thread
...@@ -330,6 +346,10 @@ typedef struct RU_proc_t_s { ...@@ -330,6 +346,10 @@ typedef struct RU_proc_t_s {
pthread_attr_t attr_FH; pthread_attr_t attr_FH;
/// pthread attributes for RU prach /// pthread attributes for RU prach
pthread_attr_t attr_prach; pthread_attr_t attr_prach;
#ifdef Rel14
/// pthread attributes for RU prach BL/CE UEs
pthread_attr_t attr_prach_br;
#endif
/// pthread attributes for RU synch thread /// pthread attributes for RU synch thread
pthread_attr_t attr_synch; pthread_attr_t attr_synch;
/// pthread attributes for asynchronous RX thread /// pthread attributes for asynchronous RX thread
...@@ -340,6 +360,10 @@ typedef struct RU_proc_t_s { ...@@ -340,6 +360,10 @@ typedef struct RU_proc_t_s {
struct sched_param sched_param_FH; struct sched_param sched_param_FH;
/// scheduling parameters for RU prach thread /// scheduling parameters for RU prach thread
struct sched_param sched_param_prach; struct sched_param sched_param_prach;
#ifdef Rel14
/// scheduling parameters for RU prach thread BL/CE UEs
struct sched_param sched_param_prach_br;
#endif
/// scheduling parameters for RU synch thread /// scheduling parameters for RU synch thread
struct sched_param sched_param_synch; struct sched_param sched_param_synch;
/// scheduling parameters for asynch_rxtx thread /// scheduling parameters for asynch_rxtx thread
...@@ -348,6 +372,10 @@ typedef struct RU_proc_t_s { ...@@ -348,6 +372,10 @@ typedef struct RU_proc_t_s {
pthread_cond_t cond_FH; pthread_cond_t cond_FH;
/// condition variable for RU prach thread /// condition variable for RU prach thread
pthread_cond_t cond_prach; pthread_cond_t cond_prach;
#ifdef Rel14
/// condition variable for RU prach thread BL/CE UEs
pthread_cond_t cond_prach_br;
#endif
/// condition variable for RU synch thread /// condition variable for RU synch thread
pthread_cond_t cond_synch; pthread_cond_t cond_synch;
/// condition variable for asynch RX/TX thread /// condition variable for asynch RX/TX thread
...@@ -360,6 +388,10 @@ typedef struct RU_proc_t_s { ...@@ -360,6 +388,10 @@ typedef struct RU_proc_t_s {
pthread_mutex_t mutex_FH; pthread_mutex_t mutex_FH;
/// mutex for RU prach /// mutex for RU prach
pthread_mutex_t mutex_prach; pthread_mutex_t mutex_prach;
#ifdef Rel14
/// mutex for RU prach BL/CE UEs
pthread_mutex_t mutex_prach_br;
#endif
/// mutex for RU synch /// mutex for RU synch
pthread_mutex_t mutex_synch; pthread_mutex_t mutex_synch;
/// mutex for eNB signal /// mutex for eNB signal
...@@ -390,20 +422,30 @@ typedef struct eNB_proc_t_s { ...@@ -390,20 +422,30 @@ typedef struct eNB_proc_t_s {
int subframe_rx; int subframe_rx;
/// subframe to act upon for PRACH /// subframe to act upon for PRACH
int subframe_prach; int subframe_prach;
#ifdef Rel14
/// subframe to act upon for reception of prach BL/CE UEs
int subframe_prach_br;
#endif
/// frame to act upon for reception /// frame to act upon for reception
int frame_rx; int frame_rx;
/// frame to act upon for transmission /// frame to act upon for transmission
int frame_tx; int frame_tx;
/// frame to act upon for PRACH /// frame to act upon for PRACH
int frame_prach; int frame_prach;
#ifdef Rel14
/// frame to act upon for PRACH BL/CE UEs
int frame_prach_br;
#endif
/// \internal This variable is protected by \ref mutex_td. /// \internal This variable is protected by \ref mutex_td.
int instance_cnt_td; int instance_cnt_td;
/// \internal This variable is protected by \ref mutex_te. /// \internal This variable is protected by \ref mutex_te.
int instance_cnt_te; int instance_cnt_te;
/// \brief Instance count for FH processing thread.
/// \brief Instance count for rx processing thread.
/// \internal This variable is protected by \ref mutex_prach. /// \internal This variable is protected by \ref mutex_prach.
int instance_cnt_prach; int instance_cnt_prach;
#ifdef Rel14
/// \internal This variable is protected by \ref mutex_prach for BL/CE UEs.
int instance_cnt_prach_br;
#endif
// instance count for over-the-air eNB synchronization // instance count for over-the-air eNB synchronization
int instance_cnt_synch; int instance_cnt_synch;
/// \internal This variable is protected by \ref mutex_asynch_rxtx. /// \internal This variable is protected by \ref mutex_asynch_rxtx.
...@@ -424,6 +466,10 @@ typedef struct eNB_proc_t_s { ...@@ -424,6 +466,10 @@ typedef struct eNB_proc_t_s {
pthread_attr_t attr_single; pthread_attr_t attr_single;
/// pthread attributes for prach processing thread /// pthread attributes for prach processing thread
pthread_attr_t attr_prach; pthread_attr_t attr_prach;
#ifdef Rel14
/// pthread attributes for prach processing thread BL/CE UEs
pthread_attr_t attr_prach_br;
#endif
/// pthread attributes for asynchronous RX thread /// pthread attributes for asynchronous RX thread
pthread_attr_t attr_asynch_rxtx; pthread_attr_t attr_asynch_rxtx;
/// scheduling parameters for parallel turbo-decoder thread /// scheduling parameters for parallel turbo-decoder thread
...@@ -434,6 +480,10 @@ typedef struct eNB_proc_t_s { ...@@ -434,6 +480,10 @@ typedef struct eNB_proc_t_s {
struct sched_param sched_param_single; struct sched_param sched_param_single;
/// scheduling parameters for prach thread /// scheduling parameters for prach thread
struct sched_param sched_param_prach; struct sched_param sched_param_prach;
#ifdef Rel14
/// scheduling parameters for prach thread
struct sched_param sched_param_prach_br;
#endif
/// scheduling parameters for asynch_rxtx thread /// scheduling parameters for asynch_rxtx thread
struct sched_param sched_param_asynch_rxtx; struct sched_param sched_param_asynch_rxtx;
/// pthread structure for parallel turbo-decoder thread /// pthread structure for parallel turbo-decoder thread
...@@ -442,12 +492,20 @@ typedef struct eNB_proc_t_s { ...@@ -442,12 +492,20 @@ typedef struct eNB_proc_t_s {
pthread_t pthread_te; pthread_t pthread_te;
/// pthread structure for PRACH thread /// pthread structure for PRACH thread
pthread_t pthread_prach; pthread_t pthread_prach;
#ifdef Rel14
/// pthread structure for PRACH thread BL/CE UEs
pthread_t pthread_prach_br;
#endif
/// condition variable for parallel turbo-decoder thread /// condition variable for parallel turbo-decoder thread
pthread_cond_t cond_td; pthread_cond_t cond_td;
/// condition variable for parallel turbo-encoder thread /// condition variable for parallel turbo-encoder thread
pthread_cond_t cond_te; pthread_cond_t cond_te;
/// condition variable for PRACH processing thread; /// condition variable for PRACH processing thread;
pthread_cond_t cond_prach; pthread_cond_t cond_prach;
#ifdef Rel14
/// condition variable for PRACH processing thread BL/CE UEs;
pthread_cond_t cond_prach_br;
#endif
/// condition variable for asynch RX/TX thread /// condition variable for asynch RX/TX thread
pthread_cond_t cond_asynch_rxtx; pthread_cond_t cond_asynch_rxtx;
/// mutex for parallel turbo-decoder thread /// mutex for parallel turbo-decoder thread
...@@ -456,16 +514,26 @@ typedef struct eNB_proc_t_s { ...@@ -456,16 +514,26 @@ typedef struct eNB_proc_t_s {
pthread_mutex_t mutex_te; pthread_mutex_t mutex_te;
/// mutex for PRACH thread /// mutex for PRACH thread
pthread_mutex_t mutex_prach; pthread_mutex_t mutex_prach;
#ifdef Rel14
/// mutex for PRACH thread for BL/CE UEs
pthread_mutex_t mutex_prach_br;
#endif
/// mutex for asynch RX/TX thread /// mutex for asynch RX/TX thread
pthread_mutex_t mutex_asynch_rxtx; pthread_mutex_t mutex_asynch_rxtx;
/// mutex for RU access to eNB processing (PDSCH/PUSCH) /// mutex for RU access to eNB processing (PDSCH/PUSCH)
pthread_mutex_t mutex_RU; pthread_mutex_t mutex_RU;
/// mutex for RU access to eNB processing (PRACH) /// mutex for RU access to eNB processing (PRACH)
pthread_mutex_t mutex_RU_PRACH; pthread_mutex_t mutex_RU_PRACH;
/// mutex for RU access to eNB processing (PRACH BR)
pthread_mutex_t mutex_RU_PRACH_br;
/// mask for RUs serving eNB (PDSCH/PUSCH) /// mask for RUs serving eNB (PDSCH/PUSCH)
int RU_mask; int RU_mask;
/// mask for RUs serving eNB (PRACH) /// mask for RUs serving eNB (PRACH)
int RU_mask_prach; int RU_mask_prach;
#ifdef Rel14
/// mask for RUs serving eNB (PRACH)
int RU_mask_prach_br;
#endif
/// parameters for turbo-decoding worker thread /// parameters for turbo-decoding worker thread
td_params tdp; td_params tdp;
/// parameters for turbo-encoding worker thread /// parameters for turbo-encoding worker thread
...@@ -631,6 +699,8 @@ typedef struct RU_t_s{ ...@@ -631,6 +699,8 @@ typedef struct RU_t_s{
int (*wakeup_rxtx)(struct PHY_VARS_eNB_s *eNB,int frame_rx,int subframe_rx); int (*wakeup_rxtx)(struct PHY_VARS_eNB_s *eNB,int frame_rx,int subframe_rx);
/// function pointer to wakeup routine in lte-enb. /// function pointer to wakeup routine in lte-enb.
int (*wakeup_prach_eNB)(struct PHY_VARS_eNB_s *eNB,struct RU_t_s *ru,int frame,int subframe); int (*wakeup_prach_eNB)(struct PHY_VARS_eNB_s *eNB,struct RU_t_s *ru,int frame,int subframe);
/// function pointer to wakeup routine in lte-enb.
int (*wakeup_prach_eNB_br)(struct PHY_VARS_eNB_s *eNB,struct RU_t_s *ru,int frame,int subframe);
/// function pointer to eNB entry routine /// function pointer to eNB entry routine
void (*eNB_top)(struct PHY_VARS_eNB_s *eNB, int frame_rx, int subframe_rx, char *string); void (*eNB_top)(struct PHY_VARS_eNB_s *eNB, int frame_rx, int subframe_rx, char *string);
/// Timing statistics /// Timing statistics
...@@ -642,6 +712,8 @@ typedef struct RU_t_s{ ...@@ -642,6 +712,8 @@ typedef struct RU_t_s{
/// received frequency-domain signal for PRACH (IF4p5 RRU) /// received frequency-domain signal for PRACH (IF4p5 RRU)
int16_t **prach_rxsigF; int16_t **prach_rxsigF;
/// received frequency-domain signal for PRACH BR (IF4p5 RRU)
int16_t **prach_rxsigF_br[4];
/// sequence number for IF5 /// sequence number for IF5
uint8_t seqno; uint8_t seqno;
/// initial timestamp used as an offset make first real timestamp 0 /// initial timestamp used as an offset make first real timestamp 0
...@@ -829,12 +901,23 @@ typedef struct PHY_VARS_eNB_s { ...@@ -829,12 +901,23 @@ typedef struct PHY_VARS_eNB_s {
IF_Module_t *if_inst; IF_Module_t *if_inst;
UL_IND_t UL_INFO; UL_IND_t UL_INFO;
pthread_mutex_t UL_INFO_mutex; pthread_mutex_t UL_INFO_mutex;
/// NFAPI RX ULSCH information
nfapi_rx_indication_pdu_t rx_pdu_list[NFAPI_RX_IND_MAX_PDU]; nfapi_rx_indication_pdu_t rx_pdu_list[NFAPI_RX_IND_MAX_PDU];
/// NFAPI RX ULSCH CRC information
nfapi_crc_indication_pdu_t crc_pdu_list[NFAPI_CRC_IND_MAX_PDU]; nfapi_crc_indication_pdu_t crc_pdu_list[NFAPI_CRC_IND_MAX_PDU];
/// NFAPI PRACH information
nfapi_preamble_pdu_t preamble_list[MAX_NUM_RX_PRACH_PREAMBLES];
#ifdef Rel14
/// NFAPI PRACH information BL/CE UEs
nfapi_preamble_pdu_t preamble_list_br[MAX_NUM_RX_PRACH_PREAMBLES];
#endif
Sched_Rsp_t Sched_INFO; Sched_Rsp_t Sched_INFO;
LTE_eNB_PDCCH pdcch_vars[2]; LTE_eNB_PDCCH pdcch_vars[2];
#ifdef Rel14
LTE_eNB_EPDCCH epdcch_vars[2]; LTE_eNB_EPDCCH epdcch_vars[2];
LTE_eNB_MPDCCH mpdcch_vars[2]; LTE_eNB_MPDCCH mpdcch_vars[2];
LTE_eNB_PRACH prach_vars_br;
#endif
LTE_eNB_COMMON common_vars; LTE_eNB_COMMON common_vars;
LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX]; LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX];
LTE_eNB_PBCH pbch; LTE_eNB_PBCH pbch;
...@@ -1364,6 +1447,13 @@ typedef struct RRU_config_s { ...@@ -1364,6 +1447,13 @@ typedef struct RRU_config_s {
int prach_FreqOffset[MAX_BANDS_PER_RRU]; int prach_FreqOffset[MAX_BANDS_PER_RRU];
/// prach_ConfigIndex for IF4p5 /// prach_ConfigIndex for IF4p5
int prach_ConfigIndex[MAX_BANDS_PER_RRU]; int prach_ConfigIndex[MAX_BANDS_PER_RRU];
#ifdef Rel14
int emtc_prach_CElevel_enable[MAX_BANDS_PER_RRU][4];
/// emtc_prach_FreqOffset for IF4p5 per CE Level
int emtc_prach_FreqOffset[MAX_BANDS_PER_RRU][4];
/// emtc_prach_ConfigIndex for IF4p5 per CE Level
int emtc_prach_ConfigIndex[MAX_BANDS_PER_RRU][4];
#endif
} RRU_config_t; } RRU_config_t;
......
...@@ -56,6 +56,8 @@ ...@@ -56,6 +56,8 @@
#define MAX_MBSFN_AREA 8 #define MAX_MBSFN_AREA 8
#define NB_RX_ANTENNAS_MAX 64
#ifdef OCP_FRAMEWORK #ifdef OCP_FRAMEWORK
#include "enums.h" #include "enums.h"
#else #else
...@@ -99,6 +101,8 @@ typedef struct { ...@@ -99,6 +101,8 @@ typedef struct {
uint8_t prach_FreqOffset; uint8_t prach_FreqOffset;
} PRACH_CONFIG_INFO; } PRACH_CONFIG_INFO;
/// PRACH-ConfigSIB or PRACH-Config from 36.331 RRC spec /// PRACH-ConfigSIB or PRACH-Config from 36.331 RRC spec
typedef struct { typedef struct {
/// Parameter: RACH_ROOT_SEQUENCE, see TS 36.211 (5.7.1). \vr{[0..837]} /// Parameter: RACH_ROOT_SEQUENCE, see TS 36.211 (5.7.1). \vr{[0..837]}
...@@ -109,6 +113,44 @@ typedef struct { ...@@ -109,6 +113,44 @@ typedef struct {
PRACH_CONFIG_INFO prach_ConfigInfo; PRACH_CONFIG_INFO prach_ConfigInfo;
} PRACH_CONFIG_COMMON; } PRACH_CONFIG_COMMON;
#ifdef Rel14
/// PRACH-eMTC-Config from 36.331 RRC spec
typedef struct {
/// Parameter: High-speed-flag, see TS 36.211 (5.7.2). \vr{[0..1]} 1 corresponds to Restricted set and 0 to Unrestricted set.
uint8_t highSpeedFlag;
/// Parameter: \f$N_\text{CS}\f$, see TS 36.211 (5.7.2). \vr{[0..15]}\n Refer to table 5.7.2-2 for preamble format 0..3 and to table 5.7.2-3 for preamble format 4.
uint8_t zeroCorrelationZoneConfig;
/// Parameter: prach-FrequencyOffset, see TS 36.211 (5.7.1). \vr{[0..94]}\n For TDD the value range is dependent on the value of \ref prach_ConfigIndex.
/// PRACH starting subframe periodicity, expressed in number of subframes available for preamble transmission (PRACH opportunities), see TS 36.211. Value 2 corresponds to 2 subframes, 4 corresponds to 4 subframes and so on. EUTRAN configures the PRACH starting subframe periodicity larger than or equal to the Number of PRACH repetitions per attempt for each CE level (numRepetitionPerPreambleAttempt).
uint8_t prach_starting_subframe_periodicity[4];
/// number of repetitions per preamble attempt per CE level
uint8_t prach_numRepetitionPerPreambleAttempt[4];
/// prach configuration index for each CE level
uint8_t prach_ConfigIndex[4];
/// indicator for CE level activation
uint8_t prach_CElevel_enable[4];
/// prach frequency offset for each CE level
uint8_t prach_FreqOffset[4];
/// indicator for CE level hopping activation
uint8_t prach_hopping_enable[4];
/// indicator for CE level hopping activation
uint8_t prach_hopping_offset[4];
} PRACH_eMTC_CONFIG_INFO;
#endif
/// PRACH-ConfigSIB or PRACH-Config from 36.331 RRC spec
typedef struct {
/// Parameter: RACH_ROOT_SEQUENCE, see TS 36.211 (5.7.1). \vr{[0..837]}
uint16_t rootSequenceIndex;
/// prach_Config_enabled=1 means enabled. \vr{[0..1]}
uint8_t prach_Config_enabled;
/// PRACH Configuration Information
PRACH_eMTC_CONFIG_INFO prach_ConfigInfo;
} PRACH_eMTC_CONFIG_COMMON;
/// Enumeration for parameter \f$N_\text{ANRep}\f$ \ref PUCCH_CONFIG_DEDICATED::repetitionFactor. /// Enumeration for parameter \f$N_\text{ANRep}\f$ \ref PUCCH_CONFIG_DEDICATED::repetitionFactor.
typedef enum { typedef enum {
n2=0, n2=0,
...@@ -546,6 +588,10 @@ typedef struct { ...@@ -546,6 +588,10 @@ typedef struct {
uint8_t nb_antenna_ports_eNB; uint8_t nb_antenna_ports_eNB;
/// PRACH_CONFIG /// PRACH_CONFIG
PRACH_CONFIG_COMMON prach_config_common; PRACH_CONFIG_COMMON prach_config_common;
#ifdef Rel14
/// PRACH_eMTC_CONFIG
PRACH_eMTC_CONFIG_COMMON prach_emtc_config_common;
#endif
/// PUCCH Config Common (from 36-331 RRC spec) /// PUCCH Config Common (from 36-331 RRC spec)
PUCCH_CONFIG_COMMON pucch_config_common; PUCCH_CONFIG_COMMON pucch_config_common;
/// PDSCH Config Common (from 36-331 RRC spec) /// PDSCH Config Common (from 36-331 RRC spec)
...@@ -1138,13 +1184,19 @@ typedef struct { ...@@ -1138,13 +1184,19 @@ typedef struct {
/// \brief ?. /// \brief ?.
/// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx. /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
/// second index: ? [0..ofdm_symbol_size*12[ /// second index: ? [0..ofdm_symbol_size*12[
int16_t *rxsigF[64]; int16_t **rxsigF;
/// \brief local buffer to compute prach_ifft (necessary in case of multiple CCs) /// \brief local buffer to compute prach_ifft (necessary in case of multiple CCs)
/// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx. /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
/// second index: ? [0..2047] (hard coded) /// second index: ? [0..2047] (hard coded)
int16_t *prach_ifft[64]; int32_t ***prach_ifft;
/// NFAPI PRACH information
nfapi_preamble_pdu_t preamble_list[MAX_NUM_RX_PRACH_PREAMBLES]; /// repetition number
#ifdef Rel14
/// indicator of first frame in a group of PRACH repetitions
int first_frame[4];
/// current repetition for each CE level
int repetition_number[4];
#endif
} LTE_eNB_PRACH; } LTE_eNB_PRACH;
typedef struct { typedef struct {
...@@ -1162,6 +1214,7 @@ typedef struct { ...@@ -1162,6 +1214,7 @@ typedef struct {
uint8_t *Msg3; uint8_t *Msg3;
} PRACH_RESOURCES_t; } PRACH_RESOURCES_t;
typedef struct { typedef struct {
/// Downlink Power offset field /// Downlink Power offset field
uint8_t dl_pow_off; uint8_t dl_pow_off;
......
...@@ -199,10 +199,13 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,re ...@@ -199,10 +199,13 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,re
/*! \brief Scheduling for eNB PRACH RX procedures /*! \brief Scheduling for eNB PRACH RX procedures
@param phy_vars_eNB Pointer to eNB variables on which to act @param phy_vars_eNB Pointer to eNB variables on which to act
@param proc Pointer to RXn-TXnp4 proc information @param br_flag indicator for eMTC PRACH
*/ */
void prach_procedures(PHY_VARS_eNB *eNB); void prach_procedures(PHY_VARS_eNB *eNB,
#ifdef Rel14
int br_flag
#endif
);
/*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index. /*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index.
@param frame_parms Pointer to DL frame parameter descriptor @param frame_parms Pointer to DL frame parameter descriptor
@param subframe Subframe index @param subframe Subframe index
......
...@@ -1179,7 +1179,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { ...@@ -1179,7 +1179,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
handle_nfapi_dlsch_pdu(eNB,proc,dl_config_pdu, handle_nfapi_dlsch_pdu(eNB,proc,dl_config_pdu,
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks-1, dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks-1,
TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data); TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data);
if (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == eNB->prach_vars.preamble_list[0].preamble_rel8.rnti) {// is RAR pdu if (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == eNB->preamble_list[0].preamble_rel8.rnti) {// is RAR pdu
generate_eNB_ulsch_params_from_rar(eNB, generate_eNB_ulsch_params_from_rar(eNB,
TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data, TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data,
...@@ -1917,107 +1917,136 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, ...@@ -1917,107 +1917,136 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
} }
} }
void prach_procedures(PHY_VARS_eNB *eNB) { void prach_procedures(PHY_VARS_eNB *eNB,
#ifdef Rel14
int br_flag
#endif
) {
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
uint16_t preamble_energy_list[64],preamble_delay_list[64]; uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4];
uint16_t preamble_max,preamble_energy_max;
uint16_t i; uint16_t i;
int subframe = eNB->proc.subframe_prach; int frame,subframe;
int frame = eNB->proc.frame_prach; #ifdef Rel14
if (br_flag==1) {
subframe = eNB->proc.subframe_prach_br;
frame = eNB->proc.frame_prach_br;
}
else
#endif
{
subframe = eNB->proc.subframe_prach;
frame = eNB->proc.frame_prach;
}
uint8_t CC_id = eNB->CC_id; uint8_t CC_id = eNB->CC_id;
RU_t *ru; RU_t *ru;
int aa=0; int aa=0;
int ru_aa; int ru_aa;
LTE_eNB_PRACH *prach_vars;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
for (i=0;i<eNB->num_RU;i++) { for (i=0;i<eNB->num_RU;i++) {
ru=eNB->RU_list[i]; ru=eNB->RU_list[i];
for (ru_aa=0;ru_aa<ru->nb_rx;ru_aa++) eNB->prach_vars.rxsigF[aa++] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; for (ru_aa=0,aa=0;ru_aa<ru->nb_rx;ru_aa++,aa++) {
eNB->prach_vars.rxsigF[aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa];
#ifdef Rel14
int ce_level;
if (br_flag==1)
for (ce_level=0;ce_level<4;ce_level++) eNB->prach_vars_br.rxsigF[aa] = eNB->RU_list[i]->prach_rxsigF_br[ce_level][ru_aa];
#endif
}
} }
rx_prach(eNB, rx_prach(eNB,
eNB->RU_list[0], eNB->RU_list[0],
preamble_energy_list, &max_preamble[0],
preamble_delay_list, &max_preamble_energy[0],
&max_preamble_delay[0],
frame, frame,
0); 0
preamble_energy_max = preamble_energy_list[0]; #ifdef Rel14
preamble_max = 0; ,br_flag
#endif
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 //#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[RAPROC] Frame %d, subframe %d : Most likely preamble %d, energy %d dB delay %d\n", LOG_D(PHY,"[RAPROC] Frame %d, subframe %d : Most likely preamble %d, energy %d dB delay %d\n",
frame,subframe, frame,subframe,
preamble_max, max_preamble[0],
preamble_energy_list[preamble_max], max_preamble_energy[0],
preamble_delay_list[preamble_max]); max_preamble_delay[0]);
//#endif //#endif
if (preamble_energy_list[preamble_max] > 580) { #ifdef Rel14
if (br_flag==1) {
// UE_id = find_next_ue_index(eNB); prach_vars = &eNB->prach_vars_br;
int prach_mask;
// if (UE_id>=0) {
// eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits prach_mask = is_prach_subframe(&eNB->frame_parms,eNB->proc.frame_prach_br,eNB->proc.subframe_prach_br);
// eNB->UE_stats[(uint32_t)UE_id].sector = 0; eNB->UL_INFO.rach_ind_br.preamble_list = eNB->preamble_list_br;
LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
eNB->Mod_id,
eNB->CC_id,
frame,
subframe,
preamble_max,
preamble_energy_max/10,
preamble_energy_max%10,
preamble_delay_list[preamble_max]);
T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), 0, for (int ind=0,ce_level=0;ce_level<4;ce_level++) {
T_INT(preamble_max), T_INT(preamble_energy_max), T_INT(preamble_delay_list[preamble_max])); if ((prach_mask&(1<<(1+ce_level)) > 0) && // prach is active and CE level has finished its repetitions
(eNB->prach_vars_br.repetition_number[ce_level]==
eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) {
if (max_preamble_energy[ind] > 580) {
eNB->UL_INFO.rach_ind_br.number_of_preambles++;
eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind];//
eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind];
// note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4
eNB->preamble_list_br[ind].preamble_rel8.rnti = 1+subframe+(eNB->prach_vars_br.first_frame[ce_level]%40);
eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is
eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1+ce_level; // CE Level
}
ind++;
}
} // ce_level
}
else
#endif
if (eNB->mac_enabled==1) { {
LTE_eNB_PRACH *prach_vars = &eNB->prach_vars; if (max_preamble_energy[0] > 580) {
uint8_t update_TA = 4; LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
uint8_t update_TA2 = 1; eNB->Mod_id,
switch (fp->N_RB_DL) { eNB->CC_id,
case 6: frame,
update_TA = 16; subframe,
break; max_preamble[0],
max_preamble_energy[0]/10,
case 25: max_preamble_energy[0]%10,
update_TA = 4; max_preamble_delay[0]);
break;
case 50:
update_TA = 2;
break;
case 75: T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), 0,
update_TA = 3; T_INT(max_preamble[0]), T_INT(max_preamble_energy[0]), T_INT(max_preamble_delay[0]));
update_TA2 = 2;
case 100: if (eNB->mac_enabled==1) {
update_TA = 1;
break; prach_vars = &eNB->prach_vars;
}
pthread_mutex_lock(&eNB->UL_INFO_mutex);
eNB->UL_INFO.rach_ind.number_of_preambles = 1; pthread_mutex_lock(&eNB->UL_INFO_mutex);
eNB->UL_INFO.rach_ind.preamble_list = prach_vars->preamble_list;
eNB->UL_INFO.rach_ind.number_of_preambles = 1;
prach_vars->preamble_list[0].preamble_rel8.timing_advance = preamble_delay_list[preamble_max]*update_TA/update_TA2; eNB->UL_INFO.rach_ind.preamble_list = eNB->preamble_list;
prach_vars->preamble_list[0].preamble_rel8.preamble = preamble_max;
prach_vars->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0];
prach_vars->preamble_list[0].instance_length = 0; //don't know exactly what this is eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0];
pthread_mutex_unlock(&eNB->UL_INFO_mutex); eNB->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here
eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0;
eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}
} // max_preamble_energy > 580
} // else br_flag
/* /*
mac_xface->initiate_ra_proc(eNB->Mod_id, mac_xface->initiate_ra_proc(eNB->Mod_id,
eNB->CC_id, eNB->CC_id,
...@@ -2026,15 +2055,13 @@ void prach_procedures(PHY_VARS_eNB *eNB) { ...@@ -2026,15 +2055,13 @@ void prach_procedures(PHY_VARS_eNB *eNB) {
preamble_delay_list[preamble_max]*update_TA/update_TA2, preamble_delay_list[preamble_max]*update_TA/update_TA2,
0,subframe,0);*/ 0,subframe,0);*/
// fill eNB->UL_info with prach information
}
/* } else { /* } else {
MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many"); MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many");
LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n", LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
eNB->Mod_id,frame, subframe); eNB->Mod_id,frame, subframe);
}*/ }*/
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
} }
......
...@@ -330,7 +330,7 @@ void config_sib2(int Mod_idP, ...@@ -330,7 +330,7 @@ void config_sib2(int Mod_idP,
cfg->emtc_config.prach_catm_zero_correlation_zone_configuration.value = radioResourceConfigCommon_BRP->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; cfg->emtc_config.prach_catm_zero_correlation_zone_configuration.value = radioResourceConfigCommon_BRP->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig;
cfg->emtc_config.prach_catm_high_speed_flag.value = radioResourceConfigCommon_BRP->prach_Config.prach_ConfigInfo.highSpeedFlag; cfg->emtc_config.prach_catm_high_speed_flag.value = radioResourceConfigCommon_BRP->prach_Config.prach_ConfigInfo.highSpeedFlag;
struct PRACH_ConfigSIB_v1310 *ext4_prach=radioResourceConfigCommonP->ext4->prach_ConfigCommon_v1310; struct PRACH_ConfigSIB_v1310 *ext4_prach=radioResourceConfigCommon_BRP->ext4->prach_ConfigCommon_v1310;
PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13; PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13;
int i; int i;
...@@ -342,40 +342,44 @@ void config_sib2(int Mod_idP, ...@@ -342,40 +342,44 @@ void config_sib2(int Mod_idP,
switch (prach_ParametersListCE_r13->list.count) { switch (prach_ParametersListCE_r13->list.count) {
case 4: case 4:
p=prach_ParametersListCE_r13->list.array[3]; p=prach_ParametersListCE_r13->list.array[3];
cfg->emtc_config.prach_ce_level_3_enable.value = 1; cfg->emtc_config.prach_ce_level_3_enable.value = 1;
cfg->emtc_config.prach_ce_level_3_configuration_index.value = p->prach_ConfigIndex_r13; cfg->emtc_config.prach_ce_level_3_configuration_index.value = p->prach_ConfigIndex_r13;
cfg->emtc_config.prach_ce_level_3_frequency_offset.value = p->prach_FreqOffset_r13; cfg->emtc_config.prach_ce_level_3_frequency_offset.value = p->prach_FreqOffset_r13;
cfg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13;
if (p->prach_StartingSubframe_r13) if (p->prach_StartingSubframe_r13)
cfg->emtc_config.prach_ce_level_3_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; cfg->emtc_config.prach_ce_level_3_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13;
cfg->emtc_config.prach_ce_level_3_hopping_enable.value = p->prach_HoppingConfig_r13; cfg->emtc_config.prach_ce_level_3_hopping_enable.value = p->prach_HoppingConfig_r13;
cfg->emtc_config.prach_ce_level_3_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; cfg->emtc_config.prach_ce_level_3_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6;
case 3: case 3:
p=prach_ParametersListCE_r13->list.array[2]; p=prach_ParametersListCE_r13->list.array[2];
cfg->emtc_config.prach_ce_level_2_enable.value = 1; cfg->emtc_config.prach_ce_level_2_enable.value = 1;
cfg->emtc_config.prach_ce_level_2_configuration_index.value = p->prach_ConfigIndex_r13; cfg->emtc_config.prach_ce_level_2_configuration_index.value = p->prach_ConfigIndex_r13;
cfg->emtc_config.prach_ce_level_2_frequency_offset.value = p->prach_FreqOffset_r13; cfg->emtc_config.prach_ce_level_2_frequency_offset.value = p->prach_FreqOffset_r13;
cfg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13;
if (p->prach_StartingSubframe_r13) if (p->prach_StartingSubframe_r13)
cfg->emtc_config.prach_ce_level_2_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; cfg->emtc_config.prach_ce_level_2_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13;
cfg->emtc_config.prach_ce_level_2_hopping_enable.value = p->prach_HoppingConfig_r13; cfg->emtc_config.prach_ce_level_2_hopping_enable.value = p->prach_HoppingConfig_r13;
cfg->emtc_config.prach_ce_level_2_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; cfg->emtc_config.prach_ce_level_2_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6;
case 2: case 2:
p=prach_ParametersListCE_r13->list.array[1]; p=prach_ParametersListCE_r13->list.array[1];
cfg->emtc_config.prach_ce_level_1_enable.value = 1; cfg->emtc_config.prach_ce_level_1_enable.value = 1;
cfg->emtc_config.prach_ce_level_1_configuration_index.value = p->prach_ConfigIndex_r13; cfg->emtc_config.prach_ce_level_1_configuration_index.value = p->prach_ConfigIndex_r13;
cfg->emtc_config.prach_ce_level_1_frequency_offset.value = p->prach_FreqOffset_r13; cfg->emtc_config.prach_ce_level_1_frequency_offset.value = p->prach_FreqOffset_r13;
cfg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13;
if (p->prach_StartingSubframe_r13) if (p->prach_StartingSubframe_r13)
cfg->emtc_config.prach_ce_level_1_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; cfg->emtc_config.prach_ce_level_1_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13;
cfg->emtc_config.prach_ce_level_1_hopping_enable.value = p->prach_HoppingConfig_r13; cfg->emtc_config.prach_ce_level_1_hopping_enable.value = p->prach_HoppingConfig_r13;
cfg->emtc_config.prach_ce_level_1_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; cfg->emtc_config.prach_ce_level_1_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6;
case 1: case 1:
p=prach_ParametersListCE_r13->list.array[0]; p=prach_ParametersListCE_r13->list.array[0];
cfg->emtc_config.prach_ce_level_0_enable.value = 1; cfg->emtc_config.prach_ce_level_0_enable.value = 1;
cfg->emtc_config.prach_ce_level_0_configuration_index.value = p->prach_ConfigIndex_r13; cfg->emtc_config.prach_ce_level_0_configuration_index.value = p->prach_ConfigIndex_r13;
cfg->emtc_config.prach_ce_level_0_frequency_offset.value = p->prach_FreqOffset_r13; cfg->emtc_config.prach_ce_level_0_frequency_offset.value = p->prach_FreqOffset_r13;
cfg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13;
if (p->prach_StartingSubframe_r13) if (p->prach_StartingSubframe_r13)
cfg->emtc_config.prach_ce_level_0_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; cfg->emtc_config.prach_ce_level_0_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13;
cfg->emtc_config.prach_ce_level_0_hopping_enable.value = p->prach_HoppingConfig_r13; cfg->emtc_config.prach_ce_level_0_hopping_enable.value = p->prach_HoppingConfig_r13;
cfg->emtc_config.prach_ce_level_0_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; cfg->emtc_config.prach_ce_level_0_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6;
} }
struct FreqHoppingParameters_r13 *ext4_freqHoppingParameters = radioResourceConfigCommonP->ext4->freqHoppingParameters_r13; struct FreqHoppingParameters_r13 *ext4_freqHoppingParameters = radioResourceConfigCommonP->ext4->freqHoppingParameters_r13;
......
...@@ -824,10 +824,18 @@ typedef struct { ...@@ -824,10 +824,18 @@ typedef struct {
uint8_t generate_rar; uint8_t generate_rar;
/// Subframe where preamble was received /// Subframe where preamble was received
uint8_t preamble_subframe; uint8_t preamble_subframe;
/// Subframe where Msg2 is to be sent
uint8_t Msg2_subframe;
/// Frame where Msg2 is to be sent
uint8_t Msg2_frame;
/// Subframe where Msg3 is to be sent /// Subframe where Msg3 is to be sent
uint8_t Msg3_subframe; uint8_t Msg3_subframe;
/// Subframe where Msg3 is to be sent /// Frame where Msg3 is to be sent
uint8_t Msg3_frame; uint8_t Msg3_frame;
/// Subframe where Msg4 is to be sent
uint8_t Msg4_subframe;
/// Frame where Msg4 is to be sent
uint8_t Msg4_frame;
/// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC. This is triggered by first ULSCH reception at eNB for new user. /// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC. This is triggered by first ULSCH reception at eNB for new user.
uint8_t generate_Msg4; uint8_t generate_Msg4;
/// Flag to indicate that eNB is waiting for ACK that UE has received Msg3. /// Flag to indicate that eNB is waiting for ACK that UE has received Msg3.
...@@ -846,6 +854,13 @@ typedef struct { ...@@ -846,6 +854,13 @@ typedef struct {
int16_t RRC_timer; int16_t RRC_timer;
/// Round of Msg3 HARQ /// Round of Msg3 HARQ
uint8_t msg3_round; uint8_t msg3_round;
#ifdef Rel14
uint8_t rach_resource_type;
uint8_t msg2_mpdcch_repetition_cnt;
uint8_t msg4_mpdcch_repetition_cnt;
uint8_t msg2_narrowband;
uint8_t msg34_narrowband;
#endif
} RA_TEMPLATE; } RA_TEMPLATE;
...@@ -962,7 +977,7 @@ typedef struct eNB_MAC_INST_s { ...@@ -962,7 +977,7 @@ typedef struct eNB_MAC_INST_s {
/// Ethernet parameters for fronthaul interface /// Ethernet parameters for fronthaul interface
eth_params_t eth_params_s; eth_params_t eth_params_s;
/// ///
uint16_t Node_id; module_id_t Mod_id;
/// frame counter /// frame counter
frame_t frame; frame_t frame;
/// subframe counter /// subframe counter
...@@ -1030,6 +1045,15 @@ typedef struct eNB_MAC_INST_s { ...@@ -1030,6 +1045,15 @@ typedef struct eNB_MAC_INST_s {
* UE part * UE part
*/ */
typedef enum {
TYPE0,
TYPE1,
TYPE1A,
TYPE2,
TYPE2A,
TYPEUESPEC
} MPDCCH_TYPES_t;
/*!\brief UE layer 2 status */ /*!\brief UE layer 2 status */
typedef enum { typedef enum {
CONNECTION_OK=0, CONNECTION_OK=0,
......
This diff is collapsed.
...@@ -208,6 +208,8 @@ void get_Msg3alloc(COMMON_channels_t *cc, ...@@ -208,6 +208,8 @@ void get_Msg3alloc(COMMON_channels_t *cc,
} }
} }
void get_Msg3allocret(COMMON_channels_t *cc, void get_Msg3allocret(COMMON_channels_t *cc,
unsigned char current_subframe, unsigned char current_subframe,
unsigned int current_frame, unsigned int current_frame,
...@@ -401,6 +403,67 @@ uint8_t get_Msg3harqpid(COMMON_channels_t *cc, ...@@ -401,6 +403,67 @@ uint8_t get_Msg3harqpid(COMMON_channels_t *cc,
} }
#ifdef Rel14
int get_numnarrowbands(long dl_Bandwidth) {
int nb_tab[6] = {1,2,4,8,12,16};
AssertFatal(dl_Bandwidth<7 || dl_Bandwidth>=0,"dl_Bandwidth not in [0..6]\n");
return(nb_tab[dl_Bandwidth]);
}
int get_numnarrowbandbits(long dl_Bandwidth) {
int nbbits_tab[6] = {0,1,2,3,4,4};
AssertFatal(dl_Bandwidth<7 || dl_Bandwidth>=0,"dl_Bandwidth not in [0..6]\n");
return(nbbits_tab[dl_Bandwidth]);
}
//This implements the frame/subframe condition for first subframe of MPDCCH transmission (Section 9.1.5 36.213, Rel 13/14)
int startSF_fdd_RA_times2[8] = {2,3,4,5,8,10,16,20};
int startSF_tdd_RA[7] = {1,2,4,5,8,10,20};
int mpdcch_sf_condition(eNB_MAC_INST *eNB,int CC_id, frame_t frameP,sub_frame_t subframeP,int rmax,MPDCCH_TYPES_t mpdcch_type) {
struct PRACH_ConfigSIB_v1310 *ext4_prach = eNB->common_channels[CC_id].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310;
int T;
switch (mpdcch_type) {
case TYPE0:
AssertFatal(1==0,"MPDCCH Type 0 not handled yet\n");
break;
case TYPE1:
AssertFatal(1==0,"MPDCCH Type 1 not handled yet\n");
break;
case TYPE1A:
AssertFatal(1==0,"MPDCCH Type 1A not handled yet\n");
break;
case TYPE2: // RAR
AssertFatal(ext4_prach->mpdcch_startSF_CSS_RA_r13!=NULL,
"mpdcch_startSF_CSS_RA_r13 is null\n");
if (eNB->common_channels[CC_id].tdd_Config==NULL) //FDD
T = rmax*startSF_fdd_RA_times2[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.fdd_r13]>>1;
else //TDD
T = rmax*startSF_tdd_RA[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.tdd_r13];
break;
case TYPE2A:
AssertFatal(1==0,"MPDCCH Type 2A not handled yet\n");
break;
case TYPEUESPEC:
AssertFatal(1==0,"MPDCCH Type UESPEC not handled yet\n");
break;
default:
return(0);
}
if (((10*frameP) + subframeP)%T == 0) return(1);
else return(0);
}
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void init_ue_sched_info(void) void init_ue_sched_info(void)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
......
...@@ -171,6 +171,7 @@ int mac_top_init_eNB() ...@@ -171,6 +171,7 @@ int mac_top_init_eNB()
RC.nb_macrlc_inst*sizeof(eNB_MAC_INST*),RC.nb_macrlc_inst,sizeof(eNB_MAC_INST)); RC.nb_macrlc_inst*sizeof(eNB_MAC_INST*),RC.nb_macrlc_inst,sizeof(eNB_MAC_INST));
LOG_D(MAC,"[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",sizeof(eNB_MAC_INST),RC.nb_macrlc_inst,RC.mac); LOG_D(MAC,"[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",sizeof(eNB_MAC_INST),RC.nb_macrlc_inst,RC.mac);
bzero(RC.mac[i],sizeof(eNB_MAC_INST)); bzero(RC.mac[i],sizeof(eNB_MAC_INST));
RC.mac[i]->Mod_id = Mod_id;
for (j=0;j<MAX_NUM_CCs;j++) { for (j=0;j<MAX_NUM_CCs;j++) {
RC.mac[i]->DL_req[j].dl_config_request_body.dl_config_pdu_list = RC.mac[i]->dl_config_pdu_list[j]; RC.mac[i]->DL_req[j].dl_config_request_body.dl_config_pdu_list = RC.mac[i]->dl_config_pdu_list[j];
RC.mac[i]->UL_req[j].ul_config_request_body.ul_config_pdu_list = RC.mac[i]->ul_config_pdu_list[j]; RC.mac[i]->UL_req[j].ul_config_request_body.ul_config_pdu_list = RC.mac[i]->ul_config_pdu_list[j];
...@@ -187,6 +188,7 @@ int mac_top_init_eNB() ...@@ -187,6 +188,7 @@ int mac_top_init_eNB()
for(Mod_id=0; Mod_id<RC.nb_macrlc_inst; Mod_id++) { for(Mod_id=0; Mod_id<RC.nb_macrlc_inst; Mod_id++) {
mac = RC.mac[Mod_id]; mac = RC.mac[Mod_id];
mac->if_inst = IF_Module_init(Mod_id); mac->if_inst = IF_Module_init(Mod_id);
UE_list = &mac->UE_list; UE_list = &mac->UE_list;
......
...@@ -205,8 +205,15 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint8_t cooperation_flag, ...@@ -205,8 +205,15 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint8_t cooperation_flag,
@param Mod_id Instance ID of eNB @param Mod_id Instance ID of eNB
@param preamble_index index of the received RA request @param preamble_index index of the received RA request
@param timing_offset Offset in samples of the received PRACH w.r.t. eNB timing. This is used to @param timing_offset Offset in samples of the received PRACH w.r.t. eNB timing. This is used to
@param rnti RA rnti corresponding to this PRACH preamble
@param rach_resource type (0=non BL/CE,1 CE level 0,2 CE level 1, 3 CE level 2,4 CE level 3)
*/ */
void initiate_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, sub_frame_t subframeP, uint16_t preamble_index,int16_t timing_offset,uint16_t rnti); void initiate_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, sub_frame_t subframeP, uint16_t preamble_index,int16_t timing_offset,uint16_t rnti
#ifdef Rel14
,
uint8_t rach_resource_type
#endif
);
/* \brief Function in eNB to fill RAR pdu when requested by PHY. This provides a single RAR SDU for the moment and returns the t-CRNTI. /* \brief Function in eNB to fill RAR pdu when requested by PHY. This provides a single RAR SDU for the moment and returns the t-CRNTI.
@param Mod_id Instance ID of eNB @param Mod_id Instance ID of eNB
......
...@@ -129,6 +129,96 @@ unsigned short fill_rar( ...@@ -129,6 +129,96 @@ unsigned short fill_rar(
return(RC.mac[module_idP]->common_channels[CC_id].RA_template[ra_idx].rnti); return(RC.mac[module_idP]->common_channels[CC_id].RA_template[ra_idx].rnti);
} }
#ifdef Rel14
//------------------------------------------------------------------------------
unsigned short fill_rar_br(eNB_MAC_INST *eNB,
const int CC_id,
const int ra_idx,
const frame_t frameP,
const sub_frame_t subframeP,
uint8_t* const dlsch_buffer,
const uint8_t ce_level
)
//------------------------------------------------------------------------------
{
RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer;
uint8_t *rar = (uint8_t *)(dlsch_buffer+1);
int i;
uint8_t nb,rballoc,reps;
uint8_t mcs,TPC,ULdelay,cqireq;
COMMON_channels_t *cc = &eNB->common_channels[CC_id];
int input_buffer_length;
AssertFatal(CC_id < MAX_NUM_CCs, "CC_id %u < MAX_NUM_CCs %u", CC_id, MAX_NUM_CCs);
AssertFatal(ra_idx >= 0 && ra_idx < 4, "RA index not in [0..3]\n");
// subheader fixed
rarh->E = 0; // First and last RAR
rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader
rarh->RAPID = cc->RA_template[ra_idx].preamble_index; // Respond to Preamble 0 only for the moment
cc->RA_template[ra_idx].timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps
rar[0] = (uint8_t)(cc->RA_template[ra_idx].timing_offset>>(2+4)); // 7 MSBs of timing advance + divide by 4
rar[1] = (uint8_t)(cc->RA_template[ra_idx].timing_offset<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4
int N_NB_index;
AssertFatal(1==0,"RAR for BL/CE Still to be finished ...\n");
// Copy the Msg2 narrowband
cc->RA_template[ra_idx].msg34_narrowband = cc->RA_template[ra_idx].msg2_narrowband;
if (ce_level<2) { //CE Level 0,1, CEmodeA
input_buffer_length =6;
N_NB_index = get_numnarrowbandbits(cc->mib->message.dl_Bandwidth);
rar[4] = (uint8_t)(cc->RA_template[ra_idx].rnti>>8);
rar[5] = (uint8_t)(cc->RA_template[ra_idx].rnti&0xff);
//cc->RA_template[ra_idx].timing_offset = 0;
nb = 0;
rballoc = mac_computeRIV(6,1+ra_idx,1); // one PRB only for UL Grant in position 1+ra_idx within Narrowband
rar[1] |= (rballoc&15)<<(4-N_NB_index); // Hopping = 0 (bit 3), 3 MSBs of rballoc
reps = 4;
mcs = 7;
TPC = 3; // no power increase
ULdelay = 0;
cqireq = 0;
rar[2] |= ((mcs&0x8)>>3); // mcs 10
rar[3] = (((mcs&0x7)<<5)) | ((TPC&7)<<2) | ((ULdelay&1)<<1) | (cqireq&1);
}
else { // CE level 2,3 => CEModeB
input_buffer_length =5;
rar[3] = (uint8_t)(cc->RA_template[ra_idx].rnti>>8);
rar[4] = (uint8_t)(cc->RA_template[ra_idx].rnti&0xff);
}
LOG_D(MAC,"[RAPROC] CC_id %d Frame %d Generating RAR BR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for ra_idx %d, CRNTI %x,preamble %d/%d,TIMING OFFSET %d\n",
CC_id,
frameP,
*(uint8_t*)rarh,rar[0],rar[1],rar[2],rar[3],rar[4],rar[5],
ra_idx,
cc->RA_template[ra_idx].rnti,
rarh->RAPID,cc->RA_template[0].preamble_index,
cc->RA_template[ra_idx].timing_offset);
if (opt_enabled) {
trace_pdu(1, dlsch_buffer, input_buffer_length, eNB->Mod_id, 2, 1,
eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,"[eNB %d][RAPROC] CC_id %d RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n",
eNB->Mod_id, CC_id, frameP, cc->RA_template[ra_idx].rnti,
rarh->RAPID, input_buffer_length);
}
return(cc->RA_template[ra_idx].rnti);
}
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint16_t uint16_t
ue_process_rar( ue_process_rar(
......
...@@ -11,6 +11,7 @@ IF_Module_t *if_inst[MAX_IF_MODULES]; ...@@ -11,6 +11,7 @@ IF_Module_t *if_inst[MAX_IF_MODULES];
Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs];
void handle_rach(UL_IND_t *UL_info) { void handle_rach(UL_IND_t *UL_info) {
int i;
if (UL_info->rach_ind.number_of_preambles>0) { if (UL_info->rach_ind.number_of_preambles>0) {
...@@ -23,8 +24,34 @@ void handle_rach(UL_IND_t *UL_info) { ...@@ -23,8 +24,34 @@ void handle_rach(UL_IND_t *UL_info) {
UL_info->subframe, UL_info->subframe,
UL_info->rach_ind.preamble_list[0].preamble_rel8.preamble, UL_info->rach_ind.preamble_list[0].preamble_rel8.preamble,
UL_info->rach_ind.preamble_list[0].preamble_rel8.timing_advance, UL_info->rach_ind.preamble_list[0].preamble_rel8.timing_advance,
UL_info->rach_ind.preamble_list[0].preamble_rel8.rnti); UL_info->rach_ind.preamble_list[0].preamble_rel8.rnti
#ifdef Rel14
,0
#endif
);
}
#ifdef Rel14
if (UL_info->rach_ind_br.number_of_preambles>0) {
AssertFatal(UL_info->rach_ind_br.number_of_preambles<5,"More than 4 preambles not supported\n");
for (i=0;i<UL_info->rach_ind_br.number_of_preambles;i++) {
AssertFatal(UL_info->rach_ind_br.preamble_list[i].preamble_rel13.rach_resource_type>0,
"Got regular PRACH preamble, not BL/CE\n");
LOG_D(MAC,"Frame %d, Subframe %d Calling initiate_ra_proc (CE_level %d)\n",UL_info->frame,UL_info->subframe,
UL_info->rach_ind_br.preamble_list[i].preamble_rel13.rach_resource_type-1);
initiate_ra_proc(UL_info->module_id,
UL_info->CC_id,
UL_info->frame,
UL_info->subframe,
UL_info->rach_ind_br.preamble_list[i].preamble_rel8.preamble,
UL_info->rach_ind_br.preamble_list[i].preamble_rel8.timing_advance,
UL_info->rach_ind_br.preamble_list[i].preamble_rel8.rnti,
UL_info->rach_ind_br.preamble_list[i].preamble_rel13.rach_resource_type);
}
UL_info->rach_ind.number_of_preambles=0;
} }
#endif
} }
void handle_ulsch(UL_IND_t *UL_info) { void handle_ulsch(UL_IND_t *UL_info) {
......
...@@ -89,6 +89,11 @@ typedef struct{ ...@@ -89,6 +89,11 @@ typedef struct{
/// RACH indication list /// RACH indication list
nfapi_rach_indication_body_t rach_ind; nfapi_rach_indication_body_t rach_ind;
#ifdef Rel14
/// RACH indication list for BR UEs
nfapi_rach_indication_body_t rach_ind_br;
#endif
/// SRS indication list /// SRS indication list
nfapi_srs_indication_body_t srs_ind; nfapi_srs_indication_body_t srs_ind;
......
...@@ -144,6 +144,9 @@ void init_eNB(int,int); ...@@ -144,6 +144,9 @@ void init_eNB(int,int);
void stop_eNB(int nb_inst); void stop_eNB(int nb_inst);
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe); void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
#ifdef Rel14
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
#endif
static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) { static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {
...@@ -153,8 +156,12 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam ...@@ -153,8 +156,12 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
// Common RX procedures subframe n // Common RX procedures subframe n
// if this is IF5 or 3GPP_eNB // if this is IF5 or 3GPP_eNB
if (eNB->RU_list[0]->function < NGFI_RAU_IF4p5) wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); if (eNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
#ifdef Rel14
wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
#endif
}
// UE-specific RX processing for subframe n // UE-specific RX processing for subframe n
phy_procedures_eNB_uespec_RX(eNB, proc, no_relay ); phy_procedures_eNB_uespec_RX(eNB, proc, no_relay );
...@@ -432,6 +439,67 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { ...@@ -432,6 +439,67 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
} }
#ifdef Rel14
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
eNB_proc_t *proc = &eNB->proc;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
int i;
if (ru!=NULL) {
pthread_mutex_lock(&proc->mutex_RU_PRACH_br);
for (i=0;i<eNB->num_RU;i++) {
if (ru == eNB->RU_list[i]) {
LOG_I(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH BR (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach_br,eNB->num_RU);
if ((proc->RU_mask_prach_br&(1<<i)) > 0)
LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information (PRACH BR) from RU %d (num_RU %d, mask %x) has not been served yet!\n",
eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach_br);
proc->RU_mask_prach_br |= (1<<i);
}
}
if (proc->RU_mask_prach_br != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return
pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
return(0);
}
else { // all RUs have provided their information so continue on and wakeup eNB processing
proc->RU_mask_prach_br = 0;
pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
}
}
// check if we have to detect PRACH first
if (is_prach_subframe(fp,frame,subframe)>0) {
LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe);
if (proc->instance_cnt_prach_br == 0) {
LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH BR\n", frame,subframe);
return;
}
// wake up thread for PRACH RX
if (pthread_mutex_lock(&proc->mutex_prach_br) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br);
exit_fun( "error locking mutex_prach" );
return;
}
++proc->instance_cnt_prach_br;
// set timing for prach thread
proc->frame_prach_br = frame;
proc->subframe_prach_br = subframe;
// the thread can now be woken up
if (pthread_cond_signal(&proc->cond_prach_br) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH BR thread %d\n", proc->thread_index);
exit_fun( "ERROR pthread_cond_signal" );
return;
}
pthread_mutex_unlock( &proc->mutex_prach_br );
}
}
#endif
/*! /*!
* \brief The prach receive thread of eNB. * \brief The prach receive thread of eNB.
* \param param is a \ref eNB_proc_t structure which contains the info what to process. * \param param is a \ref eNB_proc_t structure which contains the info what to process.
...@@ -457,7 +525,11 @@ static void* eNB_thread_prach( void* param ) { ...@@ -457,7 +525,11 @@ static void* eNB_thread_prach( void* param ) {
if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break; if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
LOG_D(PHY,"Running eNB prach procedures\n"); LOG_D(PHY,"Running eNB prach procedures\n");
prach_procedures(eNB); prach_procedures(eNB
#ifdef Rel14
,0
#endif
);
if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break; if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
} }
...@@ -468,6 +540,44 @@ static void* eNB_thread_prach( void* param ) { ...@@ -468,6 +540,44 @@ static void* eNB_thread_prach( void* param ) {
return &eNB_thread_prach_status; return &eNB_thread_prach_status;
} }
#ifdef Rel14
/*!
* \brief The prach receive thread of eNB for BL/CE UEs.
* \param param is a \ref eNB_proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
static void* eNB_thread_prach_br( void* param ) {
static int eNB_thread_prach_status;
PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param;
eNB_proc_t *proc = &eNB->proc;
// set default return value
eNB_thread_prach_status = 0;
thread_top_init("eNB_thread_prach_br",1,500000L,1000000L,20000000L);
while (!oai_exit) {
if (oai_exit) break;
if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break;
LOG_D(PHY,"Running eNB prach procedures for BL/CE UEs\n");
prach_procedures(eNB,1);
if (release_thread(&proc->mutex_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break;
}
LOG_I(PHY, "Exiting eNB thread PRACH BR\n");
eNB_thread_prach_status = 0;
return &eNB_thread_prach_status;
}
#endif
extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *); extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
...@@ -482,6 +592,9 @@ void init_eNB_proc(int inst) { ...@@ -482,6 +592,9 @@ void init_eNB_proc(int inst) {
eNB_proc_t *proc; eNB_proc_t *proc;
eNB_rxtx_proc_t *proc_rxtx; eNB_rxtx_proc_t *proc_rxtx;
pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te=NULL,*attr_synch=NULL; pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te=NULL,*attr_synch=NULL;
#ifdef Rel14
pthread_attr_t *attr_prach_br=NULL;
#endif
for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) { for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
eNB = RC.eNB[inst][CC_id]; eNB = RC.eNB[inst][CC_id];
...@@ -523,10 +636,22 @@ void init_eNB_proc(int inst) { ...@@ -523,10 +636,22 @@ void init_eNB_proc(int inst) {
pthread_attr_init( &proc->attr_te); pthread_attr_init( &proc->attr_te);
pthread_attr_init( &proc_rxtx[0].attr_rxtx); pthread_attr_init( &proc_rxtx[0].attr_rxtx);
pthread_attr_init( &proc_rxtx[1].attr_rxtx); pthread_attr_init( &proc_rxtx[1].attr_rxtx);
#ifdef Rel14
proc->instance_cnt_prach_br = -1;
proc->RU_mask_prach_br=0;
pthread_mutex_init( &proc->mutex_prach_br, NULL);
pthread_mutex_init( &proc->mutex_RU_PRACH_br,NULL);
pthread_cond_init( &proc->cond_prach_br, NULL);
pthread_attr_init( &proc->attr_prach_br);
#endif
#ifndef DEADLINE_SCHEDULER #ifndef DEADLINE_SCHEDULER
attr0 = &proc_rxtx[0].attr_rxtx; attr0 = &proc_rxtx[0].attr_rxtx;
attr1 = &proc_rxtx[1].attr_rxtx; attr1 = &proc_rxtx[1].attr_rxtx;
attr_prach = &proc->attr_prach; attr_prach = &proc->attr_prach;
#ifdef Rel14
attr_prach_br = &proc->attr_prach_br;
#endif
attr_asynch = &proc->attr_asynch_rxtx; attr_asynch = &proc->attr_asynch_rxtx;
attr_single = &proc->attr_single; attr_single = &proc->attr_single;
attr_td = &proc->attr_td; attr_td = &proc->attr_td;
...@@ -538,7 +663,9 @@ void init_eNB_proc(int inst) { ...@@ -538,7 +663,9 @@ void init_eNB_proc(int inst) {
pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] ); pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
} }
pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB ); pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB );
#ifdef Rel14
pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB );
#endif
char name[16]; char name[16];
if (eNB->single_thread_flag==0) { if (eNB->single_thread_flag==0) {
snprintf( name, sizeof(name), "RXTX0 %d", i ); snprintf( name, sizeof(name), "RXTX0 %d", i );
...@@ -601,10 +728,18 @@ void kill_eNB_proc(int inst) { ...@@ -601,10 +728,18 @@ void kill_eNB_proc(int inst) {
pthread_cond_signal( &proc_rxtx[0].cond_rxtx ); pthread_cond_signal( &proc_rxtx[0].cond_rxtx );
pthread_cond_signal( &proc_rxtx[1].cond_rxtx ); pthread_cond_signal( &proc_rxtx[1].cond_rxtx );
pthread_cond_signal( &proc->cond_prach ); pthread_cond_signal( &proc->cond_prach );
pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
pthread_join( proc->pthread_prach, (void**)&status ); pthread_join( proc->pthread_prach, (void**)&status );
pthread_mutex_destroy( &proc->mutex_prach ); pthread_mutex_destroy( &proc->mutex_prach );
pthread_cond_destroy( &proc->cond_prach ); pthread_cond_destroy( &proc->cond_prach );
#ifdef Rel14
pthread_cond_signal( &proc->cond_prach_br );
pthread_join( proc->pthread_prach_br, (void**)&status );
pthread_mutex_destroy( &proc->mutex_prach_br );
pthread_cond_destroy( &proc->cond_prach_br );
#endif
pthread_mutex_destroy(&eNB->UL_INFO_mutex); pthread_mutex_destroy(&eNB->UL_INFO_mutex);
int i; int i;
for (i=0;i<2;i++) { for (i=0;i<2;i++) {
...@@ -756,11 +891,13 @@ void init_eNB_afterRU() { ...@@ -756,11 +891,13 @@ void init_eNB_afterRU() {
AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id); AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
RC.ru[ru_id]->wakeup_rxtx = wakeup_rxtx; RC.ru[ru_id]->wakeup_rxtx = wakeup_rxtx;
RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_eNB; RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_eNB;
RC.ru[ru_id]->eNB_top = eNB_top; RC.ru[ru_id]->wakeup_prach_eNB_br = wakeup_prach_eNB_br;
RC.ru[ru_id]->eNB_top = eNB_top;
} }
} }
void init_eNB(int single_thread_flag,int wait_for_sync) { void init_eNB(int single_thread_flag,int wait_for_sync) {
int CC_id; int CC_id;
......
...@@ -479,15 +479,19 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) { ...@@ -479,15 +479,19 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) {
uint16_t packet_type; uint16_t packet_type;
uint32_t symbol_number,symbol_mask,symbol_mask_full,prach_rx; uint32_t symbol_number,symbol_mask,symbol_mask_full,prach_rx;
uint32_t got_prach_info=0;
symbol_number = 0; symbol_number = 0;
symbol_mask = 0; symbol_mask = (1<<fp->symbols_per_tti)-1;
symbol_mask_full = (1<<fp->symbols_per_tti)-1; prach_rx = 0;
prach_rx = 0;
do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number);
// grab first prach information for this new subframe
if (got_prach_info==0) {
prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx);
got_prach_info = 1;
}
if (proc->first_rx != 0) { if (proc->first_rx != 0) {
*frame = proc->frame_rx; *frame = proc->frame_rx;
*subframe = proc->subframe_rx; *subframe = proc->subframe_rx;
...@@ -503,13 +507,15 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) { ...@@ -503,13 +507,15 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) {
exit_fun("Exiting"); exit_fun("Exiting");
} }
} }
if (packet_type == IF4p5_PULFFT) { if (packet_type == IF4p5_PULFFT) symbol_mask &= (~(1<<symbol_number));
symbol_mask = symbol_mask | (1<<symbol_number); else if (packet_type == IF4p5_PRACH) prach_rx &= (~0x1);
prach_rx = (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0) ? 1 : 0; #ifdef Rel14
} else if (packet_type == IF4p5_PRACH) { else if (packet_type == IF4p5_PRACH_BR_CE0) prach_rx &= (~0x2);
prach_rx = 0; else if (packet_type == IF4p5_PRACH_BR_CE1) prach_rx &= (~0x4);
} else if (packet_type == IF4p5_PRACH_BR_CE2) prach_rx &= (~0x8);
} while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); else if (packet_type == IF4p5_PRACH_BR_CE3) prach_rx &= (~0x10);
#endif
} while( (symbol_mask > 0) || (prach_rx >0)); // haven't received all PUSCH symbols and PRACH information
} }
...@@ -895,19 +901,59 @@ static void* ru_thread_prach( void* param ) { ...@@ -895,19 +901,59 @@ static void* ru_thread_prach( void* param ) {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );
rx_prach(NULL, rx_prach(NULL,
ru, ru,
NULL,
NULL, NULL,
NULL, NULL,
proc->frame_prach, proc->frame_prach,
0); 0
#ifdef Rel14
,0
#endif
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );
if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
} }
printf( "Exiting RU thread PRACH\n"); LOG_I(PHY, "Exiting RU thread PRACH\n");
ru_thread_prach_status = 0;
return &ru_thread_prach_status;
}
#ifdef Rel14
static void* ru_thread_prach_br( void* param ) {
static int ru_thread_prach_status;
RU_t *ru = (RU_t*)param;
RU_proc_t *proc = (RU_proc_t*)&ru->proc;
// set default return value
ru_thread_prach_status = 0;
thread_top_init("ru_thread_prach_br",1,500000L,1000000L,20000000L);
while (!oai_exit) {
if (oai_exit) break;
if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break;
rx_prach(NULL,
ru,
NULL,
NULL,
NULL,
proc->frame_prach_br,
0,
1);
if (release_thread(&proc->mutex_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break;
}
LOG_I(PHY, "Exiting RU thread PRACH BR\n");
ru_thread_prach_status = 0; ru_thread_prach_status = 0;
return &ru_thread_prach_status; return &ru_thread_prach_status;
} }
#endif
int wakeup_synch(RU_t *ru){ int wakeup_synch(RU_t *ru){
...@@ -1058,6 +1104,35 @@ static inline int wakeup_prach_ru(RU_t *ru) { ...@@ -1058,6 +1104,35 @@ static inline int wakeup_prach_ru(RU_t *ru) {
return(0); return(0);
} }
#ifdef Rel14
static inline int wakeup_prach_ru_br(RU_t *ru) {
struct timespec wait;
wait.tv_sec=0;
wait.tv_nsec=5000000L;
if (pthread_mutex_timedlock(&ru->proc.mutex_prach_br,&wait) !=0) {
LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread BR (IC %d)\n", ru->proc.instance_cnt_prach_br);
exit_fun( "error locking mutex_rxtx" );
return(-1);
}
if (ru->proc.instance_cnt_prach_br==-1) {
++ru->proc.instance_cnt_prach_br;
ru->proc.frame_prach_br = ru->proc.frame_rx;
ru->proc.subframe_prach_br = ru->proc.subframe_rx;
LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
// the thread can now be woken up
AssertFatal(pthread_cond_signal(&ru->proc.cond_prach_br) == 0, "ERROR pthread_cond_signal for RU prach thread BR\n");
}
else LOG_W(PHY,"RU prach thread busy, skipping\n");
pthread_mutex_unlock( &ru->proc.mutex_prach_br );
return(0);
}
#endif
static void* ru_thread( void* param ) { static void* ru_thread( void* param ) {
static int ru_thread_status; static int ru_thread_status;
...@@ -1150,10 +1225,10 @@ static void* ru_thread( void* param ) { ...@@ -1150,10 +1225,10 @@ static void* ru_thread( void* param ) {
is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx), is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx),
proc->frame_rx,proc->subframe_rx); proc->frame_rx,proc->subframe_rx);
if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0)) if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) wakeup_prach_ru(ru);
wakeup_prach_ru(ru); #ifdef Rel14
else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1)) wakeup_prach_ru_br(ru);
#endif
// adjust for timing offset between RU // adjust for timing offset between RU
if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
...@@ -1298,7 +1373,9 @@ void init_RU_proc(RU_t *ru) { ...@@ -1298,7 +1373,9 @@ void init_RU_proc(RU_t *ru) {
RU_proc_t *proc; RU_proc_t *proc;
pthread_attr_t *attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_synch=NULL; pthread_attr_t *attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_synch=NULL;
//pthread_attr_t *attr_fep=NULL; //pthread_attr_t *attr_fep=NULL;
#ifdef Rel14
pthread_attr_t *attr_prach_br=NULL;
#endif
char name[100]; char name[100];
#ifndef OCP_FRAMEWORK #ifndef OCP_FRAMEWORK
...@@ -1335,32 +1412,37 @@ void init_RU_proc(RU_t *ru) { ...@@ -1335,32 +1412,37 @@ void init_RU_proc(RU_t *ru) {
pthread_attr_init( &proc->attr_synch); pthread_attr_init( &proc->attr_synch);
pthread_attr_init( &proc->attr_asynch_rxtx); pthread_attr_init( &proc->attr_asynch_rxtx);
pthread_attr_init( &proc->attr_fep); pthread_attr_init( &proc->attr_fep);
#ifdef Rel14
proc->instance_cnt_prach_br = -1;
pthread_mutex_init( &proc->mutex_prach_br, NULL);
pthread_cond_init( &proc->cond_prach_br, NULL);
pthread_attr_init( &proc->attr_prach_br);
#endif
#ifndef DEADLINE_SCHEDULER #ifndef DEADLINE_SCHEDULER
attr_FH = &proc->attr_FH; attr_FH = &proc->attr_FH;
attr_prach = &proc->attr_prach; attr_prach = &proc->attr_prach;
attr_synch = &proc->attr_synch; attr_synch = &proc->attr_synch;
attr_asynch = &proc->attr_asynch_rxtx; attr_asynch = &proc->attr_asynch_rxtx;
// attr_fep = &proc->attr_fep; #ifdef Rel14
attr_prach_br = &proc->attr_prach_br;
#endif
#endif #endif
pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru ); pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru );
if (ru->function == NGFI_RRU_IF4p5) { if (ru->function == NGFI_RRU_IF4p5) {
pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru ); pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
#ifdef Rel14
pthread_create( &proc->pthread_prach_br, attr_prach_br, ru_thread_prach_br, (void*)ru );
#endif
if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru);
if ((ru->if_timing == synch_to_other) || if ((ru->if_timing == synch_to_other) ||
(ru->function == NGFI_RRU_IF5) || (ru->function == NGFI_RRU_IF5) ||
(ru->function == NGFI_RRU_IF4p5)) (ru->function == NGFI_RRU_IF4p5)) pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, ru_thread_asynch_rxtx, (void*)ru );
pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, ru_thread_asynch_rxtx, (void*)ru );
snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx );
pthread_setname_np( proc->pthread_FH, name ); pthread_setname_np( proc->pthread_FH, name );
...@@ -1563,6 +1645,7 @@ void configure_ru(int idx, ...@@ -1563,6 +1645,7 @@ void configure_ru(int idx,
RRU_config_t *config = (RRU_config_t *)arg; RRU_config_t *config = (RRU_config_t *)arg;
RRU_capabilities_t *capabilities = (RRU_capabilities_t*)arg; RRU_capabilities_t *capabilities = (RRU_capabilities_t*)arg;
int ret; int ret;
int i;
LOG_I(PHY, "Received capabilities from RRU %d\n",idx); LOG_I(PHY, "Received capabilities from RRU %d\n",idx);
...@@ -1588,6 +1671,13 @@ void configure_ru(int idx, ...@@ -1588,6 +1671,13 @@ void configure_ru(int idx,
LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n", LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n",
config->prach_FreqOffset[0],config->prach_ConfigIndex[0]); config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);
#ifdef Rel14
for (i=0;i<4;i++) {
config->emtc_prach_CElevel_enable[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i];
config->emtc_prach_FreqOffset[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[i];
config->emtc_prach_ConfigIndex[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i];
}
#endif
} }
// take antenna capabilities of RRU // take antenna capabilities of RRU
ru->nb_tx = capabilities->nb_tx[0]; ru->nb_tx = capabilities->nb_tx[0];
...@@ -1621,6 +1711,13 @@ void configure_rru(int idx, ...@@ -1621,6 +1711,13 @@ void configure_rru(int idx,
config->prach_FreqOffset[0],config->prach_ConfigIndex[0]); config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);
ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0]; ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0];
ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0]; ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0];
#ifdef Rel14
for (int i=0;i<4;i++) {
ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i] = config->emtc_prach_CElevel_enable[0][i];
ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[i] = config->emtc_prach_FreqOffset[0][i];
ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i] = config->emtc_prach_ConfigIndex[0][i];
}
#endif
} }
init_frame_parms(&ru->frame_parms,1); init_frame_parms(&ru->frame_parms,1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment