From 8f621c3ed7536b91cfbac20f7bf7142915876807 Mon Sep 17 00:00:00 2001
From: Raymond Knopp <raymond.knopp@eurecom.fr>
Date: Sat, 4 Nov 2017 07:09:10 +0100
Subject: [PATCH] bugfixes for TDD in RRU (IF4p5) and timing statistics of
 fronthaul and compression.

---
 openair1/PHY/LTE_TRANSPORT/if4_tools.c        | 62 +++++++++++++------
 openair1/PHY/LTE_TRANSPORT/if4_tools.h        | 10 +--
 openair1/PHY/defs.h                           |  4 ++
 targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c |  3 +-
 targets/RT/USER/lte-ru.c                      | 21 +++++--
 5 files changed, 71 insertions(+), 29 deletions(-)

diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c
index 4528766676..38ced5d717 100644
--- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c
@@ -58,7 +58,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
   uint16_t db_fulllength, db_halflength; 
   int slotoffsetF=0, blockoffsetF=0; 
 
-  uint16_t *data_block=NULL, *i=NULL;
+  uint16_t *data_block=NULL, *i=NULL, *d=NULL;
 
   IF4p5_header_t *packet_header=NULL;
   eth_state_t *eth = (eth_state_t*) (ru->ifdevice.priv);
@@ -138,23 +138,48 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
 
     if (packet_type == IF4p5_PULFFT) {
 
+      uint16_t *rx0 = (uint16_t*) &rxdataF[0][blockoffsetF];
+      uint16_t *rx1 = (uint16_t*) &rxdataF[0][slotoffsetF];
+
+
       for (symbol_id=fp->symbols_per_tti-nsym; symbol_id<fp->symbols_per_tti; symbol_id++) {	     
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF4_SYMBOL, symbol_id );
 	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 );		
 
-	for (element_id=0; element_id<db_halflength; element_id++) {
-	  i = (uint16_t*) &rxdataF[0][blockoffsetF+element_id];
-	  data_block[element_id] = ((uint16_t) lin2alaw_if4p5[*i]) | ((uint16_t)(lin2alaw_if4p5[*(i+1)]<<8));
-	  
-	  i = (uint16_t*) &rxdataF[0][slotoffsetF+element_id];
-	  data_block[element_id+db_halflength] = ((uint16_t) lin2alaw_if4p5[*i]) | ((uint16_t)(lin2alaw_if4p5[*(i+1)]<<8));
-	  //if (element_id==0) LOG_I(PHY,"send_if4p5: symbol %d rxdata0 = (%d,%d)\n",symbol_id,*i,*(i+1));
-		
-	}
-	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 );   	
-	packet_header->frame_status &= ~(0x000f<<26);
-	packet_header->frame_status |= (symbol_id&0x000f)<<26; 
+
+	start_meas(&ru->compression);
+
+       for (element_id=0; element_id<db_halflength; element_id+=8) {
+         i = (uint16_t*) &rx0[element_id];
+          d = (uint16_t*) &data_block[element_id];
+          d[0] = ((uint16_t) lin2alaw_if4p5[i[0]])  | ((uint16_t)(lin2alaw_if4p5[i[1]]<<8));
+          d[1] = ((uint16_t) lin2alaw_if4p5[i[2]])  | ((uint16_t)(lin2alaw_if4p5[i[3]]<<8));
+          d[2] = ((uint16_t) lin2alaw_if4p5[i[4]])  | ((uint16_t)(lin2alaw_if4p5[i[5]]<<8));
+          d[3] = ((uint16_t) lin2alaw_if4p5[i[6]])  | ((uint16_t)(lin2alaw_if4p5[i[7]]<<8));
+          d[4] = ((uint16_t) lin2alaw_if4p5[i[8]])  | ((uint16_t)(lin2alaw_if4p5[i[9]]<<8));
+          d[5] = ((uint16_t) lin2alaw_if4p5[i[10]]) | ((uint16_t)(lin2alaw_if4p5[i[11]]<<8));
+          d[6] = ((uint16_t) lin2alaw_if4p5[i[12]]) | ((uint16_t)(lin2alaw_if4p5[i[13]]<<8));
+          d[7] = ((uint16_t) lin2alaw_if4p5[i[14]]) | ((uint16_t)(lin2alaw_if4p5[i[15]]<<8));
+
+          i = (uint16_t*) &rx1[element_id];
+          d = (uint16_t*) &data_block[element_id+db_halflength];
+          d[0] = ((uint16_t) lin2alaw_if4p5[i[0]])  | ((uint16_t)(lin2alaw_if4p5[i[1]]<<8));
+          d[1] = ((uint16_t) lin2alaw_if4p5[i[2]])  | ((uint16_t)(lin2alaw_if4p5[i[3]]<<8));
+          d[2] = ((uint16_t) lin2alaw_if4p5[i[4]])  | ((uint16_t)(lin2alaw_if4p5[i[5]]<<8));
+          d[3] = ((uint16_t) lin2alaw_if4p5[i[6]])  | ((uint16_t)(lin2alaw_if4p5[i[7]]<<8));
+          d[4] = ((uint16_t) lin2alaw_if4p5[i[8]])  | ((uint16_t)(lin2alaw_if4p5[i[9]]<<8));
+          d[5] = ((uint16_t) lin2alaw_if4p5[i[10]]) | ((uint16_t)(lin2alaw_if4p5[i[11]]<<8));
+          d[6] = ((uint16_t) lin2alaw_if4p5[i[12]]) | ((uint16_t)(lin2alaw_if4p5[i[13]]<<8));
+          d[7] = ((uint16_t) lin2alaw_if4p5[i[14]]) | ((uint16_t)(lin2alaw_if4p5[i[15]]<<8));
+
+        }
+
+        stop_meas(&ru->compression);
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 );   	
+	    packet_header->frame_status &= ~(0x000f<<26);
+	    packet_header->frame_status |= (symbol_id&0x000f)<<26; 
 	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 );  
+    start_meas(&ru->transport);
 	if ((ru->ifdevice.trx_write_func(&ru->ifdevice,
 					 symbol_id,
 					 &tx_buffer,
@@ -163,6 +188,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
 					 IF4p5_PULFFT)) < 0) {
 	  perror("ETHERNET write for IF4p5_PULFFT\n");
 	}
+    stop_meas(&ru->transport);
 	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 );
 	slotoffsetF  += fp->ofdm_symbol_size;
 	blockoffsetF += fp->ofdm_symbol_size;
@@ -181,7 +207,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
   } else if (packet_type >= IF4p5_PRACH && 
 	     packet_type <= IF4p5_PRACH+4) {
     // 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,packet type %x\n",frame,subframe,packet_type);
     db_fulllength = PRACH_NUM_SAMPLES;
     
     if (eth->flags == ETH_RAW_IF4p5_MODE) {
@@ -222,6 +248,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) {
 				     packet_type)) < 0) {
       perror("ETHERNET write for IF4p5_PRACH\n");
     }
+
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 );      
   } else {    
     AssertFatal(1==0, "send_IF4p5 - Unknown packet_type %x", packet_type);     
@@ -283,7 +310,7 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint
   *subframe = ((packet_header->frame_status)>>22)&0x000f;
 
   *packet_type = packet_header->sub_type; 
-
+  LOG_D(PHY,"recv_IF4p5: Frame %d, Subframe %d: packet_type %x\n",*frame,*subframe,*packet_type);
   if (*packet_type == IF4p5_PDLFFT) {          
     *symbol_number = ((packet_header->frame_status)>>26)&0x000f;         
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF4_SYMBOL, *symbol_number );
@@ -313,7 +340,6 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint
     slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size);
     blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 1 );  
-    if (ru->idx==0) LOG_D(PHY,"UL_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",ru->idx,*frame,*subframe,*symbol_number);
     for (element_id=0; element_id<db_halflength; element_id++) {
       i = (uint16_t*) &rxdataF[0][blockoffsetF+element_id];
       *i = alaw2lin_if4p5[ (data_block[element_id] & 0xff) ]; 
@@ -353,8 +379,8 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint
              PRACH_BLOCK_SIZE_BYTES);
     }
 
-    //LOG_D(PHY,"PRACH_IF4p5: CC_id %d : frame %d, subframe %d => %d dB\n",ru->idx,*frame,*subframe,
-	//  dB_fixed(signal_energy((int*)&prach_rxsigF[0][0],839)));
+    LOG_D(PHY,"PRACH_IF4p5: CC_id %d : frame %d, subframe %d => %d dB\n",ru->idx,*frame,*subframe,
+	  dB_fixed(signal_energy((int*)&prach_rxsigF[0][0],839)));
     for (idx=0;idx<ru->num_eNB;idx++) ru->wakeup_prach_eNB(ru->eNB_list[idx],ru,*frame,*subframe);
 
   } else if (*packet_type == IF4p5_PULTICK) {
diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h
index a251c62d0d..0a95e60ead 100644
--- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h
+++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h
@@ -39,11 +39,11 @@
 #define IF4p5_PULFFT 0x0019 
 #define IF4p5_PDLFFT 0x0020
 #define IF4p5_PRACH 0x0021
-#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
+#define IF4p5_PRACH_BR_CE0 0x0022
+#define IF4p5_PRACH_BR_CE1 0x0023
+#define IF4p5_PRACH_BR_CE2 0x0024
+#define IF4p5_PRACH_BR_CE3 0x0025
+#define IF4p5_PULTICK 0x0026
 
 struct IF4p5_header {  
   /// Type
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 24ea961b0e..0e44a7f8bd 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -756,6 +756,10 @@ typedef struct RU_t_s{
   time_stats_t rx_fhaul;
   /// Timing statistics (TX Fronthaul + Compression)
   time_stats_t tx_fhaul; 
+  /// Timong statistics (Compression)
+  time_stats_t compression;
+  /// Timing statistics (Fronthaul transport)
+  time_stats_t transport;
   /// RX and TX buffers for precoder output
   RU_COMMON            common;
   /// beamforming weight vectors per eNB
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c
index e323a9d5bc..ad5bbda3fe 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c
@@ -235,7 +235,8 @@ int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestam
     packet_size = UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks); 
   } else if (flags == IF4p5_PULTICK) {
     packet_size = UDP_IF4p5_PULTICK_SIZE_BYTES; 
-  } else if (flags == IF4p5_PRACH) {  
+  } else if ((flags >= IF4p5_PRACH)&&
+             (flags <= (IF4p5_PRACH+4))) {  
     packet_size = UDP_IF4p5_PRACH_SIZE_BYTES;   
   } else {
     printf("trx_eth_write_udp_IF4p5: unknown flags %d\n",flags);
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index 45f69ca414..54693f43c8 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -596,13 +596,14 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {
   symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
   do {   
     recv_IF4p5(ru, &frame_tx, &subframe_tx, &packet_type, &symbol_number);
-    if ((subframe_select(fp,*subframe) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
+    if ((subframe_select(fp,subframe_tx) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
     LOG_D(PHY,"subframe %d (%d): frame %d, subframe %d, symbol %d\n",
          *subframe,subframe_select(fp,*subframe),frame_tx,subframe_tx,symbol_number);
     if (proc->first_tx != 0) {
       *frame    = frame_tx;
       *subframe = subframe_tx;
       proc->first_tx = 0;
+      symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
     }
     else {
       AssertFatal(frame_tx == *frame,
@@ -616,7 +617,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {
     else AssertFatal(1==0,"Illegal IF4p5 packet type (should only be IF4p5_PDLFFT%d\n",packet_type);
   } while (symbol_mask != symbol_mask_full);    
 
-  if (subframe_select(fp,*subframe) == SF_DL) stop_meas(&ru->rx_fhaul);
+  if (subframe_select(fp,subframe_tx) == SF_DL) stop_meas(&ru->rx_fhaul);
 
   proc->subframe_tx  = subframe_tx;
   proc->frame_tx     = frame_tx;
@@ -871,7 +872,10 @@ static void* ru_thread_asynch_rxtx( void* param ) {
     // asynchronous receive from south (Mobipass)
     if (ru->fh_south_asynch_in) ru->fh_south_asynch_in(ru,&frame,&subframe);
     // asynchronous receive from north (RRU IF4/IF5)
-    else if (ru->fh_north_asynch_in) ru->fh_north_asynch_in(ru,&frame,&subframe);
+    else if (ru->fh_north_asynch_in) {
+       if (subframe_select(&ru->frame_parms,subframe)!=SF_UL)
+         ru->fh_north_asynch_in(ru,&frame,&subframe);
+    }
     else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n");
   }
 
@@ -1322,8 +1326,11 @@ static void* ru_stats_thread(void* param) {
        if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);
        if (ru->feptx_ofdm) print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
        if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
-       if (ru->fh_north_out) print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
-
+       if (ru->fh_north_out) {
+          print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
+          print_meas(&ru->compression,"compression",NULL,NULL);
+          print_meas(&ru->transport,"transport",NULL,NULL);
+       }
      }
   }
   return(NULL);
@@ -1911,6 +1918,8 @@ void init_RU(char *rf_config_file) {
 	ru->ifdevice.eth_params   = &ru->eth_params;
     reset_meas(&ru->rx_fhaul);
     reset_meas(&ru->tx_fhaul);
+    reset_meas(&ru->compression);
+    reset_meas(&ru->transport);
 
 	ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params);
 	printf("openair0_transport_init returns %d for ru_id %d\n",ret,ru_id);
@@ -1934,6 +1943,8 @@ void init_RU(char *rf_config_file) {
 	ru->ifdevice.eth_params   = &ru->eth_params;
     reset_meas(&ru->rx_fhaul);
     reset_meas(&ru->tx_fhaul);
+    reset_meas(&ru->compression);
+    reset_meas(&ru->transport);
 
 	ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params);
 	printf("openair0_transport_init returns %d for ru_id %d\n",ret,ru_id);
-- 
2.26.2