From 5eb6dac7db84acf874107e3b14ba83e31f13db3a Mon Sep 17 00:00:00 2001
From: Javier Morgade <javier.morgade@ieee.org>
Date: Tue, 21 Jul 2020 15:09:38 +0200
Subject: [PATCH] 	fembms: routines for decoding the UE FeMBMS/PMCH
 physical/multicast/transport channel 3GPP TS 36.211 version 14.2.0

Signed-off-by: Javier Morgade <javier.morgade@ieee.org>
---
 openair1/PHY/LTE_TRANSPORT/pmch.c        |  50 +++++++++++
 openair1/PHY/LTE_TRANSPORT/pmch_common.c | 103 ++++++++++++++++++-----
 2 files changed, 134 insertions(+), 19 deletions(-)

diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c
index 90e2836b1e7..7b508239a9f 100644
--- a/openair1/PHY/LTE_TRANSPORT/pmch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pmch.c
@@ -128,3 +128,53 @@ void generate_mch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a)
 
 }
 
+void generate_mch_khz_1dot25(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a)
+{
+
+  int G;
+  int subframe = proc->subframe_tx;
+  int frame    = proc->frame_tx;
+  //int bits;
+
+  G = get_G_khz_1dot25(&eNB->frame_parms,
+            eNB->frame_parms.N_RB_DL,
+            eNB->dlsch_MCH->harq_processes[0]->rb_alloc,
+            get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1,
+            2,proc->frame_tx,subframe,0);
+
+  //FeMBMS
+  eNB->dlsch_MCH->harq_processes[0]->Qm = get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs);
+
+
+  generate_mbsfn_pilot_khz_1dot25(eNB,proc,
+                       eNB->common_vars.txdataF,
+                       AMP);
+
+
+  AssertFatal(dlsch_encoding_fembms_pmch(eNB,
+			    proc,
+                            // a,
+			     eNB->dlsch_MCH->harq_processes[0]->pdu,
+                             1,
+                             eNB->dlsch_MCH,
+                             proc->frame_tx,
+                             subframe,
+                             &eNB->dlsch_rate_matching_stats,
+                             &eNB->dlsch_turbo_encoding_stats,
+                             &eNB->dlsch_interleaving_stats)==0,
+              "problem in dlsch_encoding");
+
+
+  /*for(bits=0;bits<G;bits++)
+        printf("%d",eNB->dlsch_MCH->harq_processes[0]->e[bits]);
+  printf("\n");*/
+
+  dlsch_scrambling(&eNB->frame_parms,1,eNB->dlsch_MCH,0,G,0,frame,subframe<<1);
+
+  mch_modulation_khz_1dot25(eNB->common_vars.txdataF,
+                 AMP,
+                 subframe,
+                 &eNB->frame_parms,
+                 eNB->dlsch_MCH);
+}
+
diff --git a/openair1/PHY/LTE_TRANSPORT/pmch_common.c b/openair1/PHY/LTE_TRANSPORT/pmch_common.c
index 03bf5a378b2..8d65dd2744d 100644
--- a/openair1/PHY/LTE_TRANSPORT/pmch_common.c
+++ b/openair1/PHY/LTE_TRANSPORT/pmch_common.c
@@ -37,23 +37,84 @@
 
 
 int is_fembms_cas_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms) {
-  uint32_t period;
-
-  if(frame_parms->NonMBSFN_config_flag ) {
-    period = 4<<frame_parms->NonMBSFN_config.radioframeAllocationPeriod;
-
-    if ((frame % period) == frame_parms->NonMBSFN_config.radioframeAllocationOffset) {
+  //uint32_t period;
+
+  //if(frame_parms->NonMBSFN_config_flag ) {
+  //  period = 4<<frame_parms->NonMBSFN_config.radioframeAllocationPeriod;
+
+  //  if ((frame % period) == frame_parms->NonMBSFN_config.radioframeAllocationOffset) {
+  //    switch (subframe) {
+  //      case 0:
+  //        return(1); //This should be CAS
+  //        break;
+  //    }
+  //  }
+  //}
+  if(frame_parms->NonMBSFN_config_flag || frame_parms->FeMBMS_active){
+   if ((frame&3)==0) {
       switch (subframe) {
         case 0:
-          return(1); //This should be CAS
-          break;
+                return(1); //This should be CAS 
+           break;
       }
-    }
+   }
+	
   }
 
   return (0);
 }
 
+int is_fembms_nonMBSFN_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms){
+   uint32_t period;
+   if(frame_parms->NonMBSFN_config_flag ) {
+      period = 4<<frame_parms->NonMBSFN_config.radioframeAllocationPeriod;
+      if ((frame % period) == frame_parms->NonMBSFN_config.radioframeAllocationOffset) {
+        switch (subframe) {
+        case 0:
+                return(1); //This should be CAS
+           break;
+        case 1:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x100) > 0)
+                return(1);
+           break;
+        case 2:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x80) > 0)
+                return(1);
+           break;
+        case 3:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x40) > 0)
+                return(1);
+           break;
+        case 4:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x20) > 0)
+                return(1);
+           break;
+        case 5:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x10) > 0)
+                return(1);
+           break;
+        case 6:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x8) > 0)
+                return(1);
+           break;
+        case 7:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x4) > 0)
+                return(1);
+           break;
+        case 8:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x2) > 0)
+                return(1);
+           break;
+        case 9:
+           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x1) > 0)
+                return(1);
+           break;
+        }
+      }
+  }
+    return (0);
+}
+
 int is_fembms_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms) {
   uint32_t period;
 
@@ -62,63 +123,67 @@ int is_fembms_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *fr
 
     if ((frame % period) == frame_parms->NonMBSFN_config.radioframeAllocationOffset) {
       switch (subframe) {
+ 	case 0:
+            return(0);
+  	  break;
         case 1:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x100) > 0)
-            return(1);
+            return(0);
 
           break;
 
         case 2:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x80) > 0)
-            return(1);
+            return(0);
 
           break;
 
         case 3:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x40) > 0)
-            return(1);
+            return(0);
 
           break;
 
         case 4:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x20) > 0)
-            return(1);
+            return(0);
 
           break;
 
         case 5:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x10) > 0)
-            return(1);
+            return(0);
 
           break;
 
         case 6:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x8) > 0)
-            return(1);
+            return(0);
 
           break;
 
         case 7:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x4) > 0)
-            return(1);
+            return(0);
 
           break;
 
         case 8:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x2) > 0)
-            return(1);
+            return(0);
 
           break;
 
         case 9:
           if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x1) > 0)
-            return(1);
+            return(0);
 
           break;
       }
-    } else { //Then regular MBSFN FeMBMS subframe
+    } else if((frame_parms->FeMBMS_active == 1 || frame_parms->NonMBSFN_config_flag == 1 ) && !is_fembms_cas_subframe(frame,subframe,frame_parms) ) { //Then regular MBSFN FeMBMS subframe
       return(1);
     }
+    return(1);
   }
 
   return(0);
-- 
GitLab