Commit 34a2945a authored by Raphael Defosseux's avatar Raphael Defosseux

Merge remote-tracking branch 'origin/fembms-enb-ue' into develop_integration_2020_w34

parents 54f7019e a8e2a8d4
......@@ -105,6 +105,7 @@ eNBs =
ue_TimersAndConstants_n310 = 20;
ue_TimersAndConstants_n311 = 1;
ue_TransmissionMode = 1;
mbms_dedicated_serving_cell = "DISABLE"
//Parameters for SIB18
rxPool_sc_CP_Len = "normal";
......
......@@ -105,6 +105,8 @@ eNBs =
ue_TimersAndConstants_n310 = 20;
ue_TimersAndConstants_n311 = 1;
ue_TransmissionMode = 1;
mbms_dedicated_serving_cell = "DISABLE"
//Parameters for SIB18
rxPool_sc_CP_Len = "normal";
......@@ -247,7 +249,6 @@ MCEs = (
);
NETWORK_INTERFACES :
{
MCE_INTERFACE_NAME_FOR_M2_ENB = "lo";
......@@ -271,12 +272,12 @@ MCEs = (
mcch_update_time = 10;
mbms_area_config_list = (
{
common_sf_allocation_period = 2; #rf4(0) rf8(1) rf16(2) rf32(3) rf64(4) rf128(5) rf256(6)
common_sf_allocation_period = 1; #rf4(0) rf8(1) rf16(2) rf32(3) rf64(4) rf128(5) rf256(6)
mbms_area_id = 0;
pmch_config_list = (
{
allocated_sf_end=64;
data_mcs=10;
allocated_sf_end=40;
data_mcs=20;
mch_scheduling_period = 0; #rf8(0)
mbms_session_list = (
{
......@@ -288,7 +289,7 @@ MCEs = (
mnc_length = 2;
}
service_id=0;
lcid=5; #this must be properly defined lcid:8+service:0 -> rab_id:5
lcid=5; #this must be properly defined lcid:8+service:0 -> rab_id:5 //with new RLC set lcid either 4 or 5
}
);
}
......@@ -296,10 +297,10 @@ MCEs = (
mbms_sf_config_list = (
{
radioframe_allocation_period=1; #n1(0) n2(1) n4(2) n8(3) n16(4) n32(5)
radioframe_allocation_period=0; #n1(0) n2(1) n4(2) n8(3) n16(4) n32(5)
radioframe_alloocation_offset=0;
num_frame="oneFrame";
subframe_allocation=57; #xx100000
subframe_allocation=59; #xx111011 #57; #xx111001
//num_frame="fourFrame";
//subframe_allocation=14548987; #
}
......
This diff is collapsed.
......@@ -102,6 +102,7 @@ eNBs =
ue_TimersAndConstants_n310 = 20;
ue_TimersAndConstants_n311 = 1;
ue_TransmissionMode = 1;
mbms_dedicated_serving_cell = "DISABLE"
//Parameters for SIB18
rxPool_sc_CP_Len = "normal";
......@@ -295,8 +296,8 @@ MCEs = (
pmch_config_list = (
{
allocated_sf_end=32;
data_mcs=14;
mch_scheduling_period = 0; #rf8(0)
data_mcs=15;
mch_scheduling_period = 0; #rf8(0) rf16(1) rf32(2) rf64(3) rf128(4) rf256(5) rf512(6) rf1024(7)
mbms_session_list = (
{
#plnm + service_id ->tmgi
......@@ -337,7 +338,7 @@ MCEs = (
offset = 0;
modification_period = 0; #rf512(0; rf1024(1)
subframe_allocation_info = 32; #BITSTRING (6bits -> one frame) xx100000
mcs = 1; #n2(0), n7(1), n13(2), n19(3)
mcs = 0; #n2(0), n7(1), n13(2), n19(3)
}
);
......@@ -416,3 +417,10 @@ NETWORK_CONTROLLER :
rrc_log_level ="info";
rrc_log_verbosity ="medium";
};
//rfsimulator :
//{
//options = ("chanmod");
//modelname = "AWGN";
//};
......@@ -620,6 +620,101 @@ function report_test {
#IPERF_TESTS=`ls $ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_iperf_ul*client*txt | grep -v mbms 2> /dev/null`
#analyzeIperfFiles
done
# FeMBMS Case
CN_CONFIG="noS1"
TMODE="fdd"
BW_CASES=(05)
for BW in ${BW_CASES[@]}
do
echo " <tr bgcolor = \"#8FBC8F\" >" >> ./test_simulator_results.html
echo " <td align = \"center\" colspan = 4 >Test FeMBMS without EPC (aka noS1): ${TMODE} -- ${BW}MHz </td>" >> ./test_simulator_results.html
echo " </tr>" >> ./test_simulator_results.html
ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_enb_fembms.log
UE_LOG=`echo $ENB_LOG | sed -e "s#enb#ue#"`
if [ -f $ENB_LOG ] && [ -f $UE_LOG ]
then
NAME_ENB=`echo $ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"`
NAME_UE=`echo $UE_LOG | sed -e "s#$ARCHIVES_LOC/##"`
echo " <tr>" >> ./test_simulator_results.html
echo " <td>$NAME_ENB --- $NAME_UE</td>" >> ./test_simulator_results.html
echo " <td>N/A</td>" >> ./test_simulator_results.html
#NB_ENB_GOT_SYNC=`egrep -c "got sync" $ENB_LOG`
NB_ENB_TUNNEL_UP=`egrep -c "Interface oaitun_enb1 successfully configured" $ENB_LOG`
NB_ENB_MTUNNEL_UP=`egrep -c "Interface oaitun_enm1 successfully configured" $ENB_LOG`
#NB_UE_GOT_SYNC=`egrep -c "rfsimulator: Success" $UE_LOG`
#NB_ENB_SYNCED_WITH_UE=`egrep -c "Generating RRCConnectionReconfigurationComplete" $UE_LOG`
NB_UE_TUNNEL_UP=`egrep -c "Interface oaitun_ue1 successfully configured" $UE_LOG`
NB_UE_MTUNNEL_UP=`egrep -c "Interface oaitun_uem1 successfully configured" $UE_LOG`
NB_UE_MBMS_PUSH_MSG=`egrep -c "TRIED TO PUSH MBMS DATA TO" $UE_LOG`
#if [ $NB_ENB_GOT_SYNC -gt 0 ] && [ $NB_UE_GOT_SYNC -gt 0 ] && [ $NB_ENB_SYNCED_WITH_UE -gt 0 ] && [ $NB_UE_MBMS_PUSH_MSG -gt 0 ]
if [ $NB_UE_MBMS_PUSH_MSG -gt 0 ]
then
echo " <td bgcolor = \"green\" >OK</td>" >> ./test_simulator_results.html
else
echo " <td bgcolor = \"red\" >KO</td>" >> ./test_simulator_results.html
fi
echo " <td><pre>" >> ./test_simulator_results.html
#if [ $NB_ENB_GOT_SYNC -gt 0 ]
#then
# echo "<font color = \"blue\">- eNB --> got sync</font>" >> ./test_simulator_results.html
#else
# echo "<font color = \"red\"><b>- eNB NEVER got sync</b></font>" >> ./test_simulator_results.html
#fi
if [ $NB_ENB_TUNNEL_UP -gt 0 ]
then
echo "<font color = \"blue\">- eNB mounted oaitun_enb1 interface</font>" >> ./test_simulator_results.html
else
echo "<font color = \"red\"><b>- eNB NEVER mounted oaitun_enb1 interface</b></font>" >> ./test_simulator_results.html
fi
if [ $NB_ENB_MTUNNEL_UP -gt 0 ]
then
echo "<font color = \"blue\">- eNB mounted oaitun_enm1 interface</font>" >> ./test_simulator_results.html
else
echo "<font color = \"red\"><b>- eNB NEVER mounted oaitun_enm1 interface</b></font>" >> ./test_simulator_results.html
fi
#if [ $NB_UE_GOT_SYNC -gt 0 ]
#then
# echo "<font color = \"blue\">- LTE UE --> got sync</font>" >> ./test_simulator_results.html
#else
# echo "<font color = \"red\"><b>- LTE UE NEVER got sync</b></font>" >> ./test_simulator_results.html
#fi
#if [ $NB_ENB_SYNCED_WITH_UE -gt 0 ]
#then
# echo "<font color = \"blue\">- LTE UE attached to eNB</font>" >> ./test_simulator_results.html
#else
# echo "<font color = \"red\"><b>- LTE UE NEVER attached to eNB</b></font>" >> ./test_simulator_results.html
#fi
if [ $NB_UE_TUNNEL_UP -gt 0 ]
then
echo "<font color = \"blue\">- LTE UE mounted oaitun_ue1 interface</font>" >> ./test_simulator_results.html
else
echo "<font color = \"red\"><b>- LTE UE NEVER mounted oaitun_ue1 interface</b></font>" >> ./test_simulator_results.html
fi
if [ $NB_UE_MTUNNEL_UP -gt 0 ]
then
echo "<font color = \"blue\">- LTE UE mounted oaitun_uem1 interface</font>" >> ./test_simulator_results.html
else
echo "<font color = \"red\"><b>- LTE UE NEVER mounted oaitun_uem1 interface</b></font>" >> ./test_simulator_results.html
fi
if [ $NB_UE_MBMS_PUSH_MSG -gt 0 ]
then
echo "<font color = \"blue\">- LTE UE tried to push ${NB_UE_MBMS_PUSH_MSG} MBMS DATA</font>" >> ./test_simulator_results.html
else
echo "<font color = \"red\"><b>- LTE UE NEVER pushed MBMS DATA</b></font>" >> ./test_simulator_results.html
fi
echo " </pre></td>" >> ./test_simulator_results.html
echo " </tr>" >> ./test_simulator_results.html
fi
#PING_LOGS=`ls $ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_ping*.log 2> /dev/null`
#analyzePingFiles
#IPERF_TESTS=`ls $ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_iperf_dl*client*txt | grep -v mbms 2> /dev/null`
#analyzeIperfFiles
#IPERF_TESTS=`ls $ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_iperf_ul*client*txt | grep -v mbms 2> /dev/null`
#analyzeIperfFiles
done
echo " </table>" >> ./test_simulator_results.html
echo " </div>" >> ./test_simulator_results.html
......
......@@ -2050,6 +2050,95 @@ function run_test_on_vm {
echo "LTE RFSIM seems to FAIL"
echo "LTE: TEST_KO" > $ARCHIVES_LOC/test_final_status.log
fi
####################
## FeMBMS CASE noS1 ##
####################
CONF_FILE=lte-fdd-fembms-basic-sim.conf
CN_CONFIG="noS1"
S1_NOS1_CFG=0
LTEBOX=0
TMODE="fdd"
FREQUENCY=2680
BW_CASES=(05)
FeMBMS_STATUS=0
for BW in ${BW_CASES[@]}
do
if [[ $BW =~ .*05.* ]]; then PRB=25; fi
if [[ $BW =~ .*10.* ]]; then PRB=50; fi
if [[ $BW =~ .*20.* ]]; then PRB=100; fi
echo "############################################################"
echo "${CN_CONFIG} : Starting the eNB with MSMS in ${TMODE}-${BW}MHz mode"
echo "############################################################"
CURRENT_ENB_LOG_FILE=${TMODE}_${BW}MHz_${CN_CONFIG}_enb_fembms.log
start_rf_sim_enb $ENB_VM_CMDS "$ENB_VM_IP_ADDR" "$EPC_VM_IP_ADDR" $CURRENT_ENB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG
echo "############################################################"
echo "${CN_CONFIG} : Starting the UE"
echo "############################################################"
CURRENT_UE_LOG_FILE=${TMODE}_${BW}MHz_${CN_CONFIG}_ue_fembms.log
start_rf_sim_ue $UE_VM_CMDS $UE_VM_IP_ADDR $ENB_VM_IP_ADDR $CURRENT_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1
if [ $UE_SYNC -eq 0 ]
then
echo "Problem w/ eNB and UE not syncing"
terminate_enb_ue_basic_sim $ENB_VM_CMDS $ENB_VM_IP_ADDR 1
terminate_enb_ue_basic_sim $UE_VM_CMDS $UE_VM_IP_ADDR 2
scp -o StrictHostKeyChecking=no ubuntu@$ENB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_ENB_LOG_FILE $ARCHIVES_LOC
scp -o StrictHostKeyChecking=no ubuntu@$UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_UE_LOG_FILE $ARCHIVES_LOC
STATUS=-1
break
fi
echo "############################################################"
echo "${CN_CONFIG} : iperf DL -- UE is server and eNB is client"
echo "############################################################"
get_enb_mbms_noS1_ip_addr $ENB_VM_CMDS $ENB_VM_IP_ADDR
IPERF_LOG_FILE=${TMODE}_${BW}MHz_${CN_CONFIG}_iperf_dl_fembms
get_ue_mbms_ip_addr $UE_VM_CMDS $UE_VM_IP_ADDR 1
THROUGHPUT=2
generic_iperf $UE_VM_CMDS $UE_VM_IP_ADDR $UE_IP_ADDR $ENB_VM_CMDS $ENB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $IPERF_LOG_FILE 1 0
scp -o StrictHostKeyChecking=no ubuntu@$UE_VM_IP_ADDR:/home/ubuntu/${IPERF_LOG_FILE}_server.txt $ARCHIVES_LOC
scp -o StrictHostKeyChecking=no ubuntu@$ENB_VM_IP_ADDR:/home/ubuntu/${IPERF_LOG_FILE}_client.txt $ARCHIVES_LOC
#check_iperf $ARCHIVES_LOC/$IPERF_LOG_FILE $THROUGHPUT
echo "############################################################"
echo "${CN_CONFIG} : Terminate enb/ue simulators"
echo "############################################################"
terminate_enb_ue_basic_sim $ENB_VM_CMDS $ENB_VM_IP_ADDR 1
terminate_enb_ue_basic_sim $UE_VM_CMDS $UE_VM_IP_ADDR 2
scp -o StrictHostKeyChecking=no ubuntu@$ENB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_ENB_LOG_FILE $ARCHIVES_LOC
scp -o StrictHostKeyChecking=no ubuntu@$UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_UE_LOG_FILE $ARCHIVES_LOC
NB_UE_FeMBMS_MESSAGES=`egrep -c "TRIED TO PUSH MBMS DATA TO" $ARCHIVES_LOC/$CURRENT_UE_LOG_FILE`
if [ $NB_UE_FeMBMS_MESSAGES -eq 0 ]; then FeMBMS_STATUS=-1; fi
done
full_l2_sim_destroy
echo "############################################################"
echo "Checking run status"
echo "############################################################"
if [ $PING_STATUS -ne 0 ]; then STATUS=-1; fi
if [ $IPERF_STATUS -ne 0 ]; then STATUS=-1; fi
if [ $FeMBMS_STATUS -eq 0 ]
then
echo "LTE FeMBMS RFSIM seems OK"
else
echo "LTE FeMBMS RFSIM seems to FAIL"
STATUS=-1
fi
if [ $STATUS -eq 0 ]
then
echo "LTE RFSIM seems OK"
echo "LTE: TEST_OK" > $ARCHIVES_LOC/test_final_status.log
else
echo "LTE RFSIM seems to FAIL"
echo "LTE: TEST_KO" > $ARCHIVES_LOC/test_final_status.log
fi
fi
if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]]
......
<!--
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The OpenAirInterface Software Alliance licenses this file to You under
the OAI Public License, Version 1.1 (the "License"); you may not use this file
except in compliance with the License.
You may obtain a copy of the License at
http://www.openairinterface.org/?page_id=698
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
For more information about the OpenAirInterface (OAI) Software Alliance:
contact@openairinterface.org
-->
<testCaseList>
<htmlTabRef>test-05-tm1-mbms-nos1-tunnel</htmlTabRef>
<htmlTabName>Test-05MHz-MBMS-TM1-noS1-tunnel</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<repeatCount>2</repeatCount>
<TestCaseRequestedList>
030201 090109
030103 000001 090103 000002 040605 000001 090109 030201
</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="000001">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
</testCase>
<testCase id="000002">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>15</idle_sleep_time_in_sec>
</testCase>
<testCase id="000003">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase id="030103">
<class>Initialize_eNB</class>
<desc>Initialize eNB (FDD/Band7/5MHz/MBMS)</desc>
<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf --noS1 --eNBs.[0].rrc_inactivity_threshold 0 --nokrnmod 1 --eNBs.[0].component_carriers.[0].eutra_band 7 --eNBs.[0].component_carriers.[0].downlink_frequency 2680000000 --eNBs.[0].component_carriers.[0].uplink_frequency_offset -120000000 --eNBs.[0].component_carriers.[0].mbms_dedicated_serving_cell ENABLE --MCEs.[0].mbms_sched_info.mbms_area_config_list.[0].pmch_config_list.[0].allocated_sf_end 512</Initialize_eNB_args>
</testCase>
<testCase id="030201">
<class>Terminate_eNB</class>
<desc>Terminate eNB</desc>
</testCase>
<testCase id="090103">
<class>Initialize_OAI_UE</class>
<desc>Initialize OAI UE (FDD/Band7/5MHz/MBMS)</desc>
<Initialize_OAI_UE_args>-C 2680000000 -r 25 --ue-rxgain 120 --ue-txgain 0 --ue-max-power 0 --ue-scan-carrier --nokrnmod 1 --noS1</Initialize_OAI_UE_args>
</testCase>
<testCase id="090109">
<class>Terminate_OAI_UE</class>
<desc>Terminate OAI UE</desc>
</testCase>
<testCase id="040605">
<class>Iperf</class>
<desc>iperf (5MHz - DL/1.5Mbps/UDP/MBMS-sink)(20 sec)</desc>
<iperf_args>-c 10.0.2.2 -u -b 1.5M -t 20 -i 1 -fm -B 10.0.2.1</iperf_args>
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
<iperf_options>sink</iperf_options>
</testCase>
</testCaseList>
......@@ -280,7 +280,7 @@ int init_rf(RU_t *ru);
void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc);
void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc);
void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe);
void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc);
void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, int fembms_flag);
bool dlsch_procedures(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
int harq_pid,
......
......@@ -275,6 +275,7 @@ void phy_config_request(PHY_Config_t *phy_config) {
fp->soundingrs_ul_config_common.srs_MaxUpPts = cfg->srs_config.max_up_pts.value;
fp->num_MBSFN_config = 0;
fp->NonMBSFN_config_flag =cfg->fembms_config.non_mbsfn_config_flag.value;
fp->FeMBMS_active = fp->NonMBSFN_config_flag;
fp->NonMBSFN_config.non_mbsfn_SubframeConfig = cfg->fembms_config.non_mbsfn_subframeconfig.value;
fp->NonMBSFN_config.radioframeAllocationPeriod = cfg->fembms_config.radioframe_allocation_period.value;
fp->NonMBSFN_config.radioframeAllocationOffset = cfg->fembms_config.radioframe_allocation_offset.value;
......
......@@ -137,7 +137,7 @@ void phy_config_sib2_ue(module_id_t Mod_id,int CC_id,
if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {
fp->MBSFN_config[i].fourFrames_flag = 0;
fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration
LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] pattern is %d\n", i,
LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] oneFrame pattern is %d\n", i,
fp->MBSFN_config[i].mbsfn_SubframeConfig);
} else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration
fp->MBSFN_config[i].fourFrames_flag = 1;
......@@ -145,7 +145,7 @@ void phy_config_sib2_ue(module_id_t Mod_id,int CC_id,
mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]|
(mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)|
(mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]<<16);
LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] pattern is %x\n", i,
LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] fourFrame pattern is %x\n", i,
fp->MBSFN_config[i].mbsfn_SubframeConfig);
}
}
......@@ -212,7 +212,7 @@ void phy_config_sib1_fembms_ue(module_id_t Mod_id,int CC_id,
LTE_DL_FRAME_PARMS *fp = &ue->frame_parms;
if (nonMBSFN_SubframeConfig != NULL) {
fp->NonMBSFN_config_flag = 0;
fp->NonMBSFN_config_flag = 1;
fp->NonMBSFN_config.radioframeAllocationPeriod=nonMBSFN_SubframeConfig->radioFrameAllocationPeriod_r14;
fp->NonMBSFN_config.radioframeAllocationOffset=nonMBSFN_SubframeConfig->radioFrameAllocationOffset_r14;
fp->NonMBSFN_config.non_mbsfn_SubframeConfig=(nonMBSFN_SubframeConfig->subframeAllocation_r14.buf[0]<<1 | nonMBSFN_SubframeConfig->subframeAllocation_r14.buf[0]>>7);
......
......@@ -93,6 +93,11 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,
frame_parms->N_RBGS = 4;
frame_parms->N_RBG = 25;
frame_parms->ofdm_symbol_size_khz_1dot25 = 2*2*6144*osf;
frame_parms->first_carrier_offset_khz_1dot25 = frame_parms->ofdm_symbol_size_khz_1dot25 - 1800*2*2;
frame_parms->nb_prefix_samples_khz_1dot25>>=(2-log2_osf);
frame_parms->nb_prefix_samples0_khz_1dot25>>=(2-log2_osf);
break;
case 75:
......@@ -104,6 +109,12 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,
frame_parms->nb_prefix_samples0=(frame_parms->nb_prefix_samples0*3)>>2;
frame_parms->N_RBGS = 4;
frame_parms->N_RBG = 25;
frame_parms->ofdm_symbol_size_khz_1dot25 = 2*6144*osf;
frame_parms->first_carrier_offset_khz_1dot25 = frame_parms->ofdm_symbol_size_khz_1dot25 - 1800*2;
frame_parms->nb_prefix_samples_khz_1dot25>>=(2-log2_osf);
frame_parms->nb_prefix_samples0_khz_1dot25>>=(2-log2_osf);
break;
case 50:
......@@ -115,6 +126,10 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,
frame_parms->nb_prefix_samples0>>=(1-log2_osf);
frame_parms->N_RBGS = 3;
frame_parms->N_RBG = 17;
frame_parms->ofdm_symbol_size_khz_1dot25 = 2*6144*osf;
frame_parms->first_carrier_offset_khz_1dot25 = frame_parms->ofdm_symbol_size_khz_1dot25 - 1800*2;
frame_parms->nb_prefix_samples_khz_1dot25>>=(2-log2_osf);
frame_parms->nb_prefix_samples0_khz_1dot25>>=(2-log2_osf);
break;
case 25:
......
......@@ -22,7 +22,7 @@
/*! \file config_ue.c
* \brief This includes FeMBMS UE Channel Estimation Procedures for FeMBMS 1.25KHz Carrier Spacing
* \author Javier Morgade
* \date 2019
* \date 2020
* \version 0.1
* \email: javier.morgade@ieee.org
* @ingroup _phy
......@@ -768,8 +768,8 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue,
module_id_t eNB_id,
uint8_t eNB_offset,
int subframe) {
int pilot_khz_1dot25[600] __attribute__((aligned(16)));
unsigned char aarx/*,aa*/;
int pilot_khz_1dot25[2*2*600] __attribute__((aligned(16)));
unsigned char aarx,aa;
//unsigned int rb;
int16_t ch[2];
short *pil,*rxF,*dl_ch/*,*ch0,*ch1,*ch11,*chp,*ch_prev*/;
......@@ -783,7 +783,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue,
int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF;
ch_offset = 0;//(l*(ue->frame_parms.ofdm_symbol_size));
symbol_offset = 0;//ch_offset;//phy_vars_ue->lte_frame_parms.ofdm_symbol_size*l;
AssertFatal( ue->frame_parms.N_RB_DL==25,"OFDM symbol size %d not yet supported for FeMBMS\n",ue->frame_parms.N_RB_DL);
//AssertFatal( ue->frame_parms.N_RB_DL==25,"OFDM symbol size %d not yet supported for FeMBMS\n",ue->frame_parms.N_RB_DL);
if( (subframe&0x1) == 0) {
f=filt24_0_khz_1dot25;
......@@ -823,7 +823,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue,
k=3;
}
if(ue->frame_parms.N_RB_DL==25) {
if(1/*ue->frame_parms.N_RB_DL==25*/) {
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
multadd_real_vector_complex_scalar(fl,
......@@ -843,7 +843,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue,
rxF+=12;
dl_ch+=16;
for(pilot_cnt=2; pilot_cnt<299; pilot_cnt+=2) {
for(pilot_cnt=2; pilot_cnt<ue->frame_parms.N_RB_DL*12-1/*299*/; pilot_cnt+=2) {
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
multadd_real_vector_complex_scalar(f,
......@@ -866,7 +866,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue,
rxF = (int16_t *)&rxdataF[aarx][((symbol_offset+1+k))]; //Skip DC offset
for(pilot_cnt=0; pilot_cnt<297; pilot_cnt+=2) {
for(pilot_cnt=0; pilot_cnt<ue->frame_parms.N_RB_DL*12-3/*297*/; pilot_cnt+=2) {
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
multadd_real_vector_complex_scalar(f,
......@@ -905,6 +905,32 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue,
}
}
// do ifft of channel estimate
for (aa=0; aa<ue->frame_parms.nb_antennas_rx*ue->frame_parms.nb_antennas_tx; aa++) {
if (ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[0][aa]) {
switch (ue->frame_parms.N_RB_DL) {
case 25:
idft(IDFT_6144,(int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[0][aa][8],
(int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[0][aa],
1);
break;
case 50:
idft(IDFT_12288,(int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[0][aa][8],
(int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[0][aa],
1);
break;
case 100:
idft(IDFT_24576,(int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[0][aa][8],
(int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[0][aa],
1);
break;
default:
break;
}
}
}
return(0);
}
......
......@@ -106,6 +106,16 @@ int lte_dl_mbsfn(PHY_VARS_eNB *phy_vars_eNB, int32_t *output,
short amp,
int subframe,
unsigned char l);
/*! \brief This function generates the 1.25KHz MBSFN reference signal sequence (36-211, Sec 6.10.1.2)
@param phy_vars_eNB Pointer to eNB variables
@param output Output vector for OFDM symbol (Frequency Domain)
@param amp Q15 amplitude
*/
int lte_dl_mbsfn_khz_1dot25(PHY_VARS_eNB *phy_vars_eNB, int32_t *output,
short amp,
int subframe);
/*!\brief This function generates the cell-specific reference signal sequence (36-211, Sec 6.10.1.1) for channel estimation upon reception
......
......@@ -20,12 +20,12 @@
*/
/*! \file PHY/LTE_TRANSPORT/dlsch_coding.c
* \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03
* \author R. Knopp
* \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03, V14.1 2017 (includes FeMBMS support)
* \author R. Knopp, J. Morgade
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \email: knopp@eurecom.fr, jaiver.morgade@ieee.org
* \note
* \warning
*/
......@@ -425,3 +425,108 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return(0);
}
int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
unsigned char *a,
uint8_t num_pdcch_symbols,
LTE_eNB_DLSCH_t *dlsch,
int frame,
uint8_t subframe,
time_stats_t *rm_stats,
time_stats_t *te_stats,
time_stats_t *i_stats) {
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe];
if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) {
LOG_E(PHY,"dlsch_encoding illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
return(-1);
}
LTE_DL_eNB_HARQ_t *hadlsch=dlsch->harq_processes[harq_pid];
uint8_t beamforming_mode=0;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
if(hadlsch->mimo_mode == TM7)
beamforming_mode = 7;
else if(hadlsch->mimo_mode == TM8)
beamforming_mode = 8;
else if(hadlsch->mimo_mode == TM9_10)
beamforming_mode = 9;
unsigned int G = get_G_khz_1dot25(frame_parms,hadlsch->nb_rb,
hadlsch->rb_alloc,
hadlsch->Qm, // mod order
hadlsch->Nl,
num_pdcch_symbols,
frame,subframe,beamforming_mode);
proc->nbEncode=0;
// if (hadlsch->Ndi == 1) { // this is a new packet
if (hadlsch->round == 0) { // this is a new packet
// Add 24-bit crc (polynomial A) to payload
unsigned int A=hadlsch->TBS; //6228;
unsigned int crc = crc24a(a,
A)>>8;
a[A>>3] = ((uint8_t *)&crc)[2];
a[1+(A>>3)] = ((uint8_t *)&crc)[1];
a[2+(A>>3)] = ((uint8_t *)&crc)[0];
// printf("CRC %x (A %d)\n",crc,A);
hadlsch->B = A+24;
// hadlsch->b = a;
memcpy(hadlsch->b,a,(A/8)+4);
if (lte_segmentation(hadlsch->b,
hadlsch->c,
hadlsch->B,
&hadlsch->C,
&hadlsch->Cplus,
&hadlsch->Cminus,
&hadlsch->Kplus,
&hadlsch->Kminus,
&hadlsch->F)<0)
return(-1);
}
for (int r=0, r_offset=0; r<hadlsch->C; r++) {
union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}};
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, proc->respEncode, TPencode);
turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req);
rdata->input=hadlsch->c[r];
rdata->Kr_bytes= ( r<hadlsch->Cminus ? hadlsch->Kminus : hadlsch->Kplus) >>3;
rdata->filler=(r==0) ? hadlsch->F : 0;
rdata->r=r;
rdata->harq_pid=harq_pid;
rdata->dlsch=dlsch;
rdata->rm_stats=rm_stats;
rdata->te_stats=te_stats;
rdata->i_stats=i_stats;
rdata->round=hadlsch->round;
rdata->r_offset=r_offset;
rdata->G=G;
if ( proc->threadPool->activated ) {
pushTpool(proc->threadPool,req);
proc->nbEncode++;
} else {
TPencode(rdata);
delNotifiedFIFO_elt(req);
}
int Qm=hadlsch->Qm;
int C=hadlsch->C;
int Nl=hadlsch->Nl;
int Gp = G/Nl/Qm;
int GpmodC = Gp%C;
if (r < (C-(GpmodC)))
r_offset += Nl*Qm * (Gp/C);
else
r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
}
return(0);
}
......@@ -20,12 +20,12 @@
*/
/*! \file PHY/LTE_TRANSPORT/dlsch_modulation.c
* \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03
* \author R. Knopp, F. Kaltenberger
* \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03, V14.1 2017 (FeMBMS)
* \author R. Knopp, F. Kaltenberger, J. Morgade
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, javier.morgade@ieee.irg
* \note
* \warning
*/
......@@ -2910,3 +2910,260 @@ int mch_modulation(int32_t **txdataF,
return (re_allocated);
}
int allocate_REs_in_RB_MCH_khz_1dot25(int32_t **txdataF,
uint32_t *jj,
uint16_t re_offset,
uint32_t symbol_offset,
uint8_t *x0,
uint8_t subframe,
uint8_t mod_order,
int16_t amp,
int16_t *qam_table_s,
uint32_t *re_allocated,
uint8_t skip_dc,
LTE_DL_FRAME_PARMS *frame_parms)
{
uint32_t tti_offset;
uint8_t re,offset;
uint8_t qam64_table_offset_re = 0;
uint8_t qam64_table_offset_im = 0;
uint8_t qam16_table_offset_re = 0;
uint8_t qam16_table_offset_im = 0;
int16_t gain_lin_QPSK;//,gain_lin_16QAM1,gain_lin_16QAM2;
int16_t re_off=re_offset;
gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
uint8_t first_re,last_re;
int inc;
#ifdef DEBUG_DLSCH_MODULATION
LOG_I(PHY,"allocate_re_MCH khz_1dot25 (mod %d): symbol_offset %d re_offset %d (%d), jj %d -> %d,%d, gain_lin_QPSK %d,txdataF %p\n",mod_order,symbol_offset,re_offset,skip_dc,*jj, x0[*jj], x0[1+*jj],gain_lin_QPSK,&txdataF[0][symbol_offset]);
#endif
/*last_re=12;
first_re=0;
inc=1;
if ((l==2)||(l==10)) {
inc=2;
first_re=1;
} else if (l==6) {
inc=2;
}*/
last_re=144; //12*12
if ((subframe&0x1)==0){ // n_sf mod 2 == 0: even
first_re=1;
offset=0;
}else{
first_re=0;
offset=3;
}
inc=1;
for (re=first_re; re<last_re; re+=inc) {
if( ((re-offset)%6) == 0 )
continue; //pilot
//if ((subframe&0x1)==0) // n_sf mod 2 == 0: even
//k = 6*m;
//else
//k = 6*m + 3;
//if ((skip_dc == 1) && (re==(6+first_re)))
if ((skip_dc == 1) && (re==(72+first_re))){
re_off=re_off - frame_parms->ofdm_symbol_size_khz_1dot25+1;
}
tti_offset = symbol_offset + re_off + re;
//LOG_I(PHY,"re %d (jj %d)\n",re,*jj);
*re_allocated = *re_allocated + 1;
switch (mod_order) {
case 2: //QPSK
LOG_D(PHY,"%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
((int16_t*)&txdataF[0][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
*jj = *jj + 1;
((int16_t*)&txdataF[0][tti_offset])[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
*jj = *jj + 1;
LOG_D(PHY,"subframe%d alloc[%d][%d][%d](%d,%d)\n",subframe,tti_offset,symbol_offset,tti_offset-symbol_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
break;
case 4: //16QAM
qam16_table_offset_re = 0;
qam16_table_offset_im = 0;
if (x0[*jj] == 1)
qam16_table_offset_re+=2;
*jj=*jj+1;
if (x0[*jj] == 1)
qam16_table_offset_im+=2;
*jj=*jj+1;
if (x0[*jj] == 1)
qam16_table_offset_re+=1;
*jj=*jj+1;
if (x0[*jj] == 1)
qam16_table_offset_im+=1;
*jj=*jj+1;
((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s[qam16_table_offset_re];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s[qam16_table_offset_im];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
break;
case 6: //64QAM
qam64_table_offset_re = 0;
qam64_table_offset_im = 0;
if (x0[*jj] == 1)
qam64_table_offset_re+=4;
*jj=*jj+1;
if (x0[*jj] == 1)
qam64_table_offset_im+=4;
*jj=*jj+1;
if (x0[*jj] == 1)
qam64_table_offset_re+=2;
*jj=*jj+1;
if (x0[*jj] == 1)
qam64_table_offset_im+=2;
*jj=*jj+1;
if (x0[*jj] == 1)
qam64_table_offset_re+=1;
*jj=*jj+1;
if (x0[*jj] == 1)
qam64_table_offset_im+=1;
*jj=*jj+1;
((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
break;
}
}
return(0);
}
int mch_modulation_khz_1dot25(int32_t **txdataF,
int16_t amp,
uint32_t subframe_offset,
LTE_DL_FRAME_PARMS *frame_parms,
LTE_eNB_DLSCH_t *dlsch)
{
uint8_t nsymb,nsymb_pmch;
uint32_t i,jj,re_allocated,symbol_offset;
uint16_t l,rb,re_offset;
uint8_t skip_dc=0;
uint8_t mod_order = dlsch->harq_processes[0]->Qm;
int16_t qam16_table_a[4],qam64_table_a[8];//,qam16_table_b[4],qam64_table_b[8];
int16_t *qam_table_s;
nsymb_pmch = 1;
nsymb = (frame_parms->Ncp == NORMAL) ? 14 : 12;
if (mod_order == 4)
for (i=0; i<4; i++) {
qam16_table_a[i] = (int16_t)(((int32_t)qam16_table[i]*amp)>>15);
}
else if (mod_order == 6)
for (i=0; i<8; i++) {
qam64_table_a[i] = (int16_t)(((int32_t)qam64_table[i]*amp)>>15);
}
jj=0;
re_allocated=0;
// LOG_I(PHY,"num_pdcch_symbols %d, nsymb %d\n",num_pdcch_symbols,nsymb);
for (l=0; l<nsymb_pmch; l++) {
#ifdef DEBUG_DLSCH_MODULATION
LOG_I(PHY,"Generating khz_1dot25 MCH (mod %d) in subframe %d for symbol %d\n",mod_order, subframe_offset,l);
#endif
re_offset = frame_parms->first_carrier_offset_khz_1dot25;
symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe_offset*nsymb));
for (rb=0; rb<frame_parms->N_RB_DL; rb++) {
if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL
if (rb==(frame_parms->N_RB_DL>>1))
skip_dc = 1;
else
skip_dc = 0;
}
if (mod_order == 4)
qam_table_s = qam16_table_a;
else if (mod_order == 6)
qam_table_s = qam64_table_a;
else
qam_table_s = NULL;
//LOG_I(PHY,"Allocated rb %d, subframe_offset %d,amp %d\n",rb,subframe_offset,amp);
allocate_REs_in_RB_MCH_khz_1dot25(txdataF,
&jj,
re_offset,
symbol_offset,
dlsch->harq_processes[0]->eDL,
subframe_offset,
mod_order,
amp,
qam_table_s,
&re_allocated,
skip_dc,
frame_parms);
re_offset+=144; // go to next RB 12*12
// check if we crossed the symbol boundary and skip DC
if (re_offset >= frame_parms->ofdm_symbol_size_khz_1dot25) {
if (skip_dc == 0) //even number of RBs (doesn't straddle DC)
re_offset=1;
else
re_offset=73; // odd number of RBs
}
}
}
#ifdef DEBUG_DLSCH_MODULATION
LOG_I(PHY,"generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset,1/*transmission mode*/));
LOG_I(PHY,"generate_dlsch(MCH) : jj = %d,re_allocated = %d\n",jj,re_allocated);
#endif
return (re_allocated);
}
......@@ -20,12 +20,12 @@
*/
/*! \file PHY/LTE_TRANSPORT/pbch.c
* \brief Top-level routines for generating and decoding the PBCH/BCH physical/transport channel V8.6 2009-03
* \author R. Knopp, F. Kaltenberger
* \brief Top-level routines for generating and decoding the PBCH/BCH physical/transport channel V8.6 2009-03, V14.1 (FeMBMS)
* \author R. Knopp, F. Kaltenberger, J. Morgade
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger.fr
* \email: knopp@eurecom.fr,florian.kaltenberger.fr, javier.morgade@ieee.org
* \note
* \warning
*/
......@@ -139,6 +139,285 @@ int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
return(0);
}
void pbch_scrambling_fembms(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t *pbch_e,
uint32_t length)
{
int i;
uint8_t reset;
uint32_t x1, x2, s=0;
reset = 1;
// x1 is set in lte_gold_generic
x2 = frame_parms->Nid_cell + (1<<9); //this is c_init for FeMBMS in 36.211 Sec 6.6.1
// msg("pbch_scrambling: Nid_cell = %d\n",x2);
for (i=0; i<length; i++) {
if ((i&0x1f)==0) {
s = lte_gold_generic(&x1, &x2, reset);
// printf("lte_gold[%d]=%x\n",i,s);
reset = 0;
}
pbch_e[i] = (pbch_e[i]&1) ^ ((s>>(i&0x1f))&1);
}
}
int generate_pbch_fembms(LTE_eNB_PBCH *eNB_pbch,
int32_t **txdataF,
int amp,
LTE_DL_FRAME_PARMS *frame_parms,
uint8_t *pbch_pdu,
uint8_t frame_mod4)
{
int i, l;
uint32_t pbch_D,pbch_E;//,pbch_coded_bytes;
uint8_t pbch_a[PBCH_A>>3];
uint8_t RCC;
uint32_t nsymb = (frame_parms->Ncp==NORMAL) ? 14:12;
uint32_t pilots;
#ifdef INTERFERENCE_MITIGATION
uint32_t pilots_2;
#endif
uint32_t second_pilot = (frame_parms->Ncp==NORMAL) ? 4 : 3;
uint32_t jj=0;
uint32_t re_allocated=0;
uint32_t rb, re_offset, symbol_offset;
uint16_t amask=0;
pbch_D = 16+PBCH_A;
pbch_E = (frame_parms->Ncp==NORMAL) ? 1920 : 1728; //RE/RB * #RB * bits/RB (QPSK)
// pbch_E_bytes = pbch_coded_bits>>3;
LOG_D(PHY,"%s(eNB_pbch:%p txdataF:%p amp:%d frame_parms:%p pbch_pdu:%p frame_mod4:%d)\n", __FUNCTION__, eNB_pbch, txdataF, amp, frame_parms, pbch_pdu, frame_mod4==0);
if (frame_mod4==0) {
bzero(pbch_a,PBCH_A>>3);
bzero(eNB_pbch->pbch_e,pbch_E);
memset(eNB_pbch->pbch_d,LTE_NULL,96);
// Encode data
// CRC attachment
// crc = (uint16_t) (crc16(pbch_pdu, pbch_crc_bits-16) >> 16);
/*
// scramble crc with PBCH CRC mask (Table 5.3.1.1-1 of 3GPP 36.212-860)
switch (frame_parms->nb_antenna_ports_eNB) {
case 1:
crc = crc ^ (uint16_t) 0;
break;
case 2:
crc = crc ^ (uint16_t) 0xFFFF;
break;
case 4:
crc = crc ^ (uint16_t) 0xAAAA;
break;
default:
msg("[PBCH] Unknown number of TX antennas!\n");
break;
}
*/
// Fix byte endian of PBCH (bit 23 goes in first)
for (i=0; i<(PBCH_A>>3); i++)
pbch_a[(PBCH_A>>3)-i-1] = pbch_pdu[i];
// pbch_data[i] = ((char*) &crc)[0];
// pbch_data[i+1] = ((char*) &crc)[1];
//#ifdef DEBUG_PBCH
for (i=0; i<(PBCH_A>>3); i++)
LOG_D(PHY,"[PBCH] pbch_data[%d] = %x\n",i,pbch_a[i]);
//#endif
if (frame_parms->nb_antenna_ports_eNB == 1)
amask = 0x0000;
else {
switch (frame_parms->nb_antenna_ports_eNB) {
case 1:
amask = 0x0000;
break;
case 2:
amask = 0xffff;
break;
case 4:
amask = 0x5555;
}
}
ccodelte_encode(PBCH_A,2,pbch_a,eNB_pbch->pbch_d+96,amask);
#ifdef DEBUG_PBCH_ENCODING
for (i=0; i<16+PBCH_A; i++)
LOG_D(PHY,"%d : (%d,%d,%d)\n",i,*(eNB_pbch->pbch_d+96+(3*i)),*(eNB_pbch->pbch_d+97+(3*i)),*(eNB_pbch->pbch_d+98+(3*i)));
#endif //DEBUG_PBCH_ENCODING
// Bit collection
/*
j2=0;
for (j=0;j<pbch_crc_bits*3+12;j++) {
if ((pbch_coded_data[j]&0x80) > 0) { // bit is to be transmitted
pbch_coded_data2[j2++] = pbch_coded_data[j]&1;
//Bit is repeated
if ((pbch_coded_data[j]&0x40)>0)
pbch_coded_data2[j2++] = pbch_coded_data[j]&1;
}
}
#ifdef DEBUG_PBCH
msg("[PBCH] rate matched bits=%d, pbch_coded_bits=%d, pbch_crc_bits=%d\n",j2,pbch_coded_bits,pbch_crc_bits);
#endif
#ifdef DEBUG_PBCH
LOG_M"pbch_encoded_output2.m","pbch_encoded_out2",
pbch_coded_data2,
pbch_coded_bits,
1,
4);
#endif //DEBUG_PBCH
*/
#ifdef DEBUG_PBCH_ENCODING
LOG_D(PHY,"Doing PBCH interleaving for %d coded bits, e %p\n",pbch_D,eNB_pbch->pbch_e);
#endif
RCC = sub_block_interleaving_cc(pbch_D,eNB_pbch->pbch_d+96,eNB_pbch->pbch_w);
lte_rate_matching_cc(RCC,pbch_E,eNB_pbch->pbch_w,eNB_pbch->pbch_e);
#ifdef DEBUG_PBCH_ENCODING
LOG_D(PHY,"PBCH_e:\n");
for (i=0; i<pbch_E; i++)
LOG_D(PHY,"%d %d\n",i,*(eNB_pbch->pbch_e+i));
LOG_D(PHY,"\n");
#endif
#ifdef DEBUG_PBCH
if (frame_mod4==0) {
LOG_M("pbch_e.m","pbch_e",
eNB_pbch->pbch_e,
pbch_E,
1,
4);
for (i=0; i<16; i++)
printf("e[%d] %d\n",i,eNB_pbch->pbch_e[i]);
}
#endif //DEBUG_PBCH
// scrambling
pbch_scrambling_fembms(frame_parms,
eNB_pbch->pbch_e,
pbch_E);
#ifdef DEBUG_PBCH
if (frame_mod4==0) {
LOG_M("pbch_e_s.m","pbch_e_s",
eNB_pbch->pbch_e,
pbch_E,
1,
4);
for (i=0; i<16; i++)
printf("e_s[%d] %d\n",i,eNB_pbch->pbch_e[i]);
}
#endif //DEBUG_PBCH
} // frame_mod4==0
// modulation and mapping (slot 1, symbols 0..3)
for (l=(nsymb>>1); l<(nsymb>>1)+4; l++) {
pilots=0;
#ifdef INTERFERENCE_MITIGATION
pilots_2 = 0;
#endif
if ((l==0) || (l==(nsymb>>1))) {
pilots=1;
#ifdef INTERFERENCE_MITIGATION
pilots_2=1;
#endif
}
if ((l==1) || (l==(nsymb>>1)+1)) {
pilots=1;
}
if ((l==second_pilot)||(l==(second_pilot+(nsymb>>1)))) {
pilots=1;
}
#ifdef DEBUG_PBCH
LOG_D(PHY,"[PBCH] l=%d, pilots=%d\n",l,pilots);
#endif
re_offset = frame_parms->ofdm_symbol_size-3*12;
symbol_offset = frame_parms->ofdm_symbol_size*l;
for (rb=0; rb<6; rb++) {
#ifdef DEBUG_PBCH
LOG_D(PHY,"RB %d, jj %d, re_offset %d, symbol_offset %d, pilots %d, nushift %d\n",rb,jj,re_offset, symbol_offset, pilots,frame_parms->nushift);
#endif
allocate_pbch_REs_in_RB(frame_parms,
txdataF,
&jj,
re_offset,
symbol_offset,
&eNB_pbch->pbch_e[frame_mod4*(pbch_E>>2)],
pilots,
#ifdef INTERFERENCE_MITIGATION
(pilots_2==1)?(amp/3):amp,
#else
amp,
#endif
&re_allocated);
re_offset+=12; // go to next RB
// check if we crossed the symbol boundary and skip DC
if (re_offset >= frame_parms->ofdm_symbol_size)
re_offset=1;
}
// }
}
#ifdef DEBUG_PBCH
printf("[PBCH] txdataF=\n");
for (i=0; i<frame_parms->ofdm_symbol_size; i++) {
printf("%d=>(%d,%d)",i,((short*)&txdataF[0][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[0],
((short*)&txdataF[0][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[1]);
if (frame_parms->nb_antenna_ports_eNB!=1) {
printf("(%d,%d)\n",((short*)&txdataF[1][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[0],
((short*)&txdataF[1][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[1]);
} else {
printf("\n");
}
}
#endif
return(0);
}
void pbch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t *pbch_e,
uint32_t length)
......
......@@ -20,12 +20,12 @@
*/
/*! \file PHY/LTE_TRANSPORT/pilots_mbsfn.c
* \brief Top-level routines for generating DL mbsfn reference signals
* \authors S. Paranche, R. Knopp
* \brief Top-level routines for generating DL mbsfn reference signals / DL mbsfn reference signals for FeMBMS
* \authors S. Paranche, R. Knopp, J. Morgade
* \date 2012
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \email: knopp@eurecom.fr, javier.morgade@ieee.org
* \note
* \warning
*/
......@@ -85,3 +85,31 @@ int generate_mbsfn_pilot(PHY_VARS_eNB *eNB,
}
int generate_mbsfn_pilot_khz_1dot25(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
int32_t **txdataF,
int16_t amp)
{
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
uint32_t subframe_offset,Nsymb;
int subframe = proc->subframe_tx;
if (subframe<0 || subframe>= 10) {
LOG_E(PHY,"generate_mbsfn_pilots_subframe: subframe not in range (%d)\n",subframe);
return(-1);
}
Nsymb = (frame_parms->Ncp==NORMAL) ? 7 : 6;
subframe_offset = subframe*frame_parms->ofdm_symbol_size*Nsymb<<1;
lte_dl_mbsfn_khz_1dot25(eNB,
&txdataF[0][subframe_offset+0],
amp,subframe);
return(0);
}
......@@ -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);
}
......@@ -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);
......
......@@ -67,6 +67,7 @@
#if !defined(SI_RNTI)
#define SI_RNTI (rnti_t)0xffff
#define SI_RNTI_MBMS (rnti_t)0xfff9
#endif
#if !defined(M_RNTI)
#define M_RNTI (rnti_t)0xfffd
......
......@@ -270,6 +270,9 @@ int is_pmch_subframe(frame_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parm
*/
int is_fembms_cas_subframe(frame_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms);
int is_fembms_nonMBSFN_subframe (frame_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms);
/*!
\brief Return the status of MBSFN in this frame/subframe
@param frame Frame index
......
......@@ -123,6 +123,42 @@ int32_t dlsch_encoding(PHY_VARS_eNB *eNB,
time_stats_t *te_stats,
time_stats_t *i_stats);
/** \fn dlsch_encoding(PHY_VARS_eNB *eNB,
uint8_t *input_buffer,
LTE_DL_FRAME_PARMS *frame_parms,
uint8_t num_pdcch_symbols,
LTE_eNB_DLSCH_t *dlsch,
int frame,
uint8_t subframe)
\brief This function performs a subset of the bit-coding functions for LTE as described in 36-212, Release 8.Support is limited to turbo-coded channels (DLSCH/ULSCH). The implemented functions are:
- CRC computation and addition
- Code block segmentation and sub-block CRC addition
- Channel coding (Turbo coding)
- Rate matching (sub-block interleaving, bit collection, selection and transmission
- Code block concatenation
@param eNB Pointer to eNB PHY context
@param input_buffer Pointer to input buffer for sub-frame
@param frame_parms Pointer to frame descriptor structure
@param num_pdcch_symbols Number of PDCCH symbols in this subframe
@param dlsch Pointer to dlsch to be encoded
@param frame Frame number
@param subframe Subframe number
@param rm_stats Time statistics for rate-matching
@param te_stats Time statistics for turbo-encoding
@param i_stats Time statistics for interleaving
@returns status
*/
int32_t dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
uint8_t *a,
uint8_t num_pdcch_symbols,
LTE_eNB_DLSCH_t *dlsch,
int frame,
uint8_t subframe,
time_stats_t *rm_stats,
time_stats_t *te_stats,
time_stats_t *i_stats);
......@@ -269,6 +305,30 @@ int mch_modulation(int32_t **txdataF,
LTE_DL_FRAME_PARMS *frame_parms,
LTE_eNB_DLSCH_t *dlsch);
/*
\brief This function is the top-level routine for generation of the sub-frame signal (frequency-domain) for MCH.
@param txdataF Table of pointers for frequency-domain TX signals
@param amp Amplitude of signal
@param subframe_offset Offset of this subframe in units of subframes (usually 0)
@param frame_parms Pointer to frame descriptor
@param dlsch Pointer to DLSCH descriptor for this allocation
*/
int mch_modulation_khz_1dot25(int32_t **txdataF,
int16_t amp,
uint32_t subframe_offset,
LTE_DL_FRAME_PARMS *frame_parms,
LTE_eNB_DLSCH_t *dlsch);
/** \brief Top-level generation function for eNB TX of MBSFN
@param phy_vars_eNB Pointer to eNB variables
@param a Pointer to transport block
@param abstraction_flag
*/
void generate_mch_khz_1dot25(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc,uint8_t *a);
/** \brief Top-level generation function for eNB TX of MBSFN
@param phy_vars_eNB Pointer to eNB variables
@param a Pointer to transport block
......@@ -318,6 +378,12 @@ int32_t generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB,
uint16_t slot,
int first_pilot_only);
int32_t generate_mbsfn_pilot_khz_1dot25(PHY_VARS_eNB *phy_vars_eNB,
L1_rxtx_proc_t *proc,
int32_t **txdataF,
int16_t amp);
int32_t generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB,
L1_rxtx_proc_t *proc,
int32_t **txdataF,
......@@ -350,6 +416,13 @@ int32_t generate_pbch(LTE_eNB_PBCH *eNB_pbch,
uint8_t *pbch_pdu,
uint8_t frame_mod4);
int32_t generate_pbch_fembms(LTE_eNB_PBCH *eNB_pbch,
int32_t **txdataF,
int32_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
uint8_t *pbch_pdu,
uint8_t frame_mod16);
......
......@@ -88,7 +88,7 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input
if(nb_symbols == 0) return;
short temp[4096*4] __attribute__((aligned(32)));
short temp[2*2*6144*4] __attribute__((aligned(32)));
unsigned short i,j;
short k;
......@@ -125,9 +125,23 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input
case 3072:
idftsize = IDFT_3072;
break;
case 4096:
idftsize = IDFT_4096;
break;
case 6144:
idftsize= IDFT_6144;
break;
case 12288:
idftsize= IDFT_12288;
break;
case 24576:
idftsize= IDFT_24576;
break;
default:
idftsize = IDFT_512;
break;
......
......@@ -20,12 +20,12 @@
*/
/*! \file phy_procedures_lte_eNB.c
* \brief Implementation of eNB procedures from 36.213 LTE specifications
* \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
* \brief Implementation of eNB procedures from 36.213 LTE specifications / FeMBMS 36.231 LTE procedures v14.2
* \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas, J. Morgade
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk, javier.morgade@ieee.org
* \note
* \warning
*/
......@@ -122,12 +122,32 @@ lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subfr
}
#ifdef MBMS_NFAPI_SCHEDULER
void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, int fembms_flag) {
int subframe = proc->subframe_tx;
// This is DL-Cell spec pilots in Control region
generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1);
if(eNB->dlsch_MCH->active==1)
generate_mch (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/);
if(!fembms_flag){
generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1);
generate_mbsfn_pilot(eNB,proc,
eNB->common_vars.txdataF,
AMP);
}else
generate_mbsfn_pilot_khz_1dot25(eNB,proc,
eNB->common_vars.txdataF,
AMP);
if(eNB->dlsch_MCH->active==1){
if(!fembms_flag){
generate_mch (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/);
}
else{
generate_mch_khz_1dot25 (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/);
}
LOG_D(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (TBS %d) fembms %d \n",
eNB->Mod_id,proc->frame_tx,subframe,
eNB->dlsch_MCH->harq_processes[0]->TBS>>3,fembms_flag);
}
eNB->dlsch_MCH->active = 0;
}
#else
......@@ -171,6 +191,80 @@ void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
}
#endif
void common_signal_procedures_fembms (PHY_VARS_eNB *eNB,int frame, int subframe) {
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
int **txdataF = eNB->common_vars.txdataF;
uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
if((frame&3)!=0 /*&& subframe != 0*/)
return;
LOG_I(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s index:%d\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?",(frame&15)/4);
// generate Cell-Specific Reference Signals for both slots
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
if(subframe_select(fp,subframe) == SF_S)
generate_pilots_slot(eNB,
txdataF,
AMP,
subframe<<1,1);
else
generate_pilots_slot(eNB,
txdataF,
AMP,
subframe<<1,0);
// check that 2nd slot is for DL
if (subframe_select (fp, subframe) == SF_DL)
generate_pilots_slot (eNB, txdataF, AMP, (subframe << 1) + 1, 0);
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME (VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX, 0);
// First half of PSS/SSS (FDD, slot 0)
if (subframe == 0) {
//if (fp->frame_type == FDD) {
generate_pss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 0);
generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 5 : 4, 0);
//}
/// First half of SSS (TDD, slot 1)
//if (fp->frame_type == TDD) {
generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 1);
//}
// generate PBCH (Physical Broadcast CHannel) info
/// generate PBCH
if ((frame&15)==0) {
//AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n");
if (eNB->pbch_configured!=1) return;
eNB->pbch_configured=0;
}
T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
T_BUFFER(pbch_pdu, 3));
generate_pbch_fembms (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, (frame & 15)/4);
} //else if ((subframe == 1) && (fp->frame_type == TDD)) {
//generate_pss (txdataF, AMP, fp, 2, 2);
// }
// Second half of PSS/SSS (FDD, slot 10)
else if ((subframe == 5) && (fp->frame_type == FDD) && is_fembms_nonMBSFN_subframe(frame,subframe,fp)) {
generate_pss (txdataF, AMP, &eNB->frame_parms, (fp->Ncp == NORMAL) ? 6 : 5, 10);
generate_sss (txdataF, AMP, &eNB->frame_parms, (fp->Ncp == NORMAL) ? 5 : 4, 10);
}
// Second-half of SSS (TDD, slot 11)
// else if ((subframe == 5) && (fp->frame_type == TDD)) {
// generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 11);
// }
// Second half of PSS (TDD, slot 12)
// else if ((subframe == 6) && (fp->frame_type == TDD)) {
// generate_pss (txdataF, AMP, fp, 2, 12);
// }
}
void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
int **txdataF = eNB->common_vars.txdataF;
......@@ -417,12 +511,30 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
}
if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
if (is_fembms_pmch_subframe(frame,subframe,fp)) {
#ifdef MBMS_NFAPI_SCHEDULER
pmch_procedures(eNB,proc,1);
LOG_D(MAC,"frame %d, subframe %d -> PMCH\n",frame,subframe);
return;
#endif
}else if(is_fembms_cas_subframe(frame,subframe,fp) || is_fembms_nonMBSFN_subframe(frame,subframe,fp)){
LOG_D(MAC,"frame %d, subframe %d -> CAS\n",frame,subframe);
common_signal_procedures_fembms(eNB,proc->frame_tx, proc->subframe_tx);
//return;
}
if((!is_fembms_cas_subframe(frame,subframe,fp)) && (!is_fembms_nonMBSFN_subframe(frame,subframe,fp))){
if (is_pmch_subframe(frame,subframe,fp)) {
#ifdef MBMS_NFAPI_SCHEDULER
pmch_procedures(eNB,proc,0);
#else
pmch_procedures(eNB,proc);
#endif
} else {
// this is not a pmch subframe, so generate PSS/SSS/PBCH
common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx);
}
}
}
// clear existing ulsch dci allocations before applying info from MAC (this is table
......@@ -508,6 +620,18 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
if (do_meas==1) start_meas(&eNB->dlsch_ue_specific);
if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
if (is_fembms_pmch_subframe(frame,subframe,fp)) {
#ifdef MBMS_NFAPI_SCHEDULER
pmch_procedures(eNB,proc,1);
return;
#endif
}else if(is_fembms_cas_subframe(frame,subframe,fp)){
common_signal_procedures_fembms(eNB,proc->frame_tx, proc->subframe_tx);
}
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
// Now scan UE specific DLSCH
......
......@@ -41,6 +41,17 @@
* \warning
*/
/*! \function feptx0
* \brief Implementation of ofdm encoding for FeMBMS profile in one eNB
* \author J. Morgade
* \date 2020
* \version 0.1
* \email: javier.morgade@ieee.org
* \note
* \warning
*/
#include "PHY/defs_eNB.h"
#include "PHY/phy_extern.h"
......@@ -76,7 +87,7 @@ void feptx0(RU_t *ru,
int slot_sizeF = (fp->ofdm_symbol_size) * ((fp->Ncp==1) ? 6 : 7);
int subframe = ru->proc.tti_tx;
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+slot , 1 );
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(slot&1) , 1 );
slot_offset = slot*(fp->samples_per_tti>>1); //slot_offset = subframe*fp->samples_per_tti + (slot*(fp->samples_per_tti>>1));
......@@ -91,7 +102,17 @@ void feptx0(RU_t *ru,
fp->nb_prefix_samples,
CYCLIC_PREFIX);
} else {
if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)){
if(is_fembms_pmch_subframe(ru->proc.frame_tx,subframe,fp)){
if((slot&1)==0){//just use one slot chance
PHY_ofdm_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF],
(int*)&ru->common.txdata[aa][slot_offset],
fp->ofdm_symbol_size_khz_1dot25,
1,
fp->ofdm_symbol_size_khz_1dot25>>2,
CYCLIC_PREFIX);
LOG_D(HW,"Generating PMCH FeMBMS TX subframe %d %d\n",subframe,fp->ofdm_symbol_size_khz_1dot25);
}
} else if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)){
if ((slot&1) == 0) {//just use one slot chance
normal_prefix_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF],
(int*)&ru->common.txdata[aa][slot_offset],
......
......@@ -2383,10 +2383,12 @@ void ue_pbch_procedures(uint8_t eNB_id,
if (pbch_phase>=4)
pbch_phase=0;
if((ue->frame_parms.FeMBMS_active == 0)|| is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || first_run) {
for (pbch_trials=0; pbch_trials<4; pbch_trials++) {
//for (pbch_phase=0;pbch_phase<4;pbch_phase++) {
//LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, eNB_id %d)\n",ue->Mod_id,frame_rx,pbch_phase,ue->frame_parms.Nid_cell,eNB_id);
if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms)) {
if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || ue->frame_parms.FeMBMS_active) {
pbch_tx_ant = rx_pbch_fembms(&ue->common_vars,
ue->pbch_vars[eNB_id],
&ue->frame_parms,
......@@ -2431,9 +2433,10 @@ void ue_pbch_procedures(uint8_t eNB_id,
ue->pbch_vars[eNB_id]->pdu_errors_conseq = 0;
if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms)) {
if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || ue->frame_parms.FeMBMS_active) {
frame_tx = (int)((ue->pbch_vars[eNB_id]->decoded_output[2]&31)<<1);
frame_tx += ue->pbch_vars[eNB_id]->decoded_output[1]>>7;
frame_tx = frame_tx<<4;
frame_tx +=4*pbch_phase;
} else {
frame_tx = (((int)(ue->pbch_vars[eNB_id]->decoded_output[2]&0x03))<<8);
......@@ -2501,6 +2504,17 @@ void ue_pbch_procedures(uint8_t eNB_id,
ue->frame_parms.phich_config_common.phich_duration,
ue->frame_parms.phich_config_common.phich_resource);
}
LOG_I(PHY,"[UE %d] frame %d, subframe %d, Received PBCH (MIB): nb_antenna_ports_eNB %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n",
ue->Mod_id,
frame_rx,
subframe_rx,
ue->frame_parms.nb_antenna_ports_eNB,
pbch_tx_ant,
frame_tx,
ue->frame_parms.N_RB_DL,
ue->frame_parms.phich_config_common.phich_duration,
ue->frame_parms.phich_config_common.phich_resource);
} else {
if (LOG_DUMPFLAG(DEBUG_UE_PHYPROC)) {
LOG_E(PHY,"[UE %d] frame %d, subframe %d, Error decoding PBCH!\n",
......@@ -2533,6 +2547,8 @@ void ue_pbch_procedures(uint8_t eNB_id,
ue->pbch_vars[eNB_id]->pdu_errors_conseq);
}
} //if((ue->frame_parms.FeMBMS_active == 0)|| is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || first_run)
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT);
}
......@@ -2877,10 +2893,19 @@ void ue_pmch_procedures(PHY_VARS_UE *ue,
int l;
int ret=0;
if (is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms)) {
if (is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) || fembms_flag) {
// LOG_D(PHY,"ue calling pmch subframe ..\n ");
LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Querying for PMCH demodulation\n",
ue->Mod_id,frame_rx,subframe_rx);
if(fembms_flag)
pmch_mcs = ue_query_mch_fembms(ue->Mod_id,
CC_id,
frame_rx,
subframe_rx,
eNB_id,
&sync_area,
&mcch_active);
else
pmch_mcs = ue_query_mch(ue->Mod_id,
CC_id,
frame_rx,
......@@ -2960,6 +2985,7 @@ void ue_pmch_procedures(PHY_VARS_UE *ue,
LOG_D(PHY,"start turbo decode for MCH %d.%d --> Nl %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->Nl);
LOG_D(PHY,"start turbo decode for MCH %d.%d --> G %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->G);
LOG_D(PHY,"start turbo decode for MCH %d.%d --> Kmimo %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->Kmimo);
ret = dlsch_decoding(ue,
ue->pdsch_vars_MCH[ue->current_thread_id[subframe_rx]][0]->llr[0],
&ue->frame_parms,
......@@ -3007,14 +3033,14 @@ void ue_pmch_procedures(PHY_VARS_UE *ue,
// if (subframe_rx==9)
// mac_xface->macphy_exit("Why are we exiting here?");
} else { // decoding successful
LOG_D(PHY,"[UE %d] Frame %d, subframe %d: PMCH OK (%d,%d), passing to L2 (TBS %d, iter %d,G %d)\n",
LOG_I(PHY,"[UE %d] Frame %d, subframe %d: PMCH OK (%d,%d), passing to L2 (TBS %d, iter %d,G %d) ret %d\n",
ue->Mod_id,
frame_rx,subframe_rx,
ue->dlsch_mcch_errors[sync_area][0],
ue->dlsch_mtch_errors[sync_area][0],
ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3,
ue->dlsch_MCH[0]->max_turbo_iterations,
ue->dlsch_MCH[0]->harq_processes[0]->G);
ue->dlsch_MCH[0]->harq_processes[0]->G,ret);
ue_send_mch_sdu(ue->Mod_id,
CC_id,
frame_rx,
......@@ -3022,6 +3048,8 @@ void ue_pmch_procedures(PHY_VARS_UE *ue,
ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3,
eNB_id,// not relevant in eMBMS context
sync_area);
//dump_mch(ue,0,ue->dlsch_MCH[0]->harq_processes[0]->G,subframe_rx);
//exit_fun("nothing to add");
if (mcch_active == 1)
ue->dlsch_mcch_received[sync_area][0]++;
......@@ -4429,6 +4457,15 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,
ue_pmch_procedures(ue,proc,eNB_id,abstraction_flag,1);
return 0;
} else { // this gets closed at end
if (is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || is_fembms_nonMBSFN_subframe(frame_rx,subframe_rx,&ue->frame_parms) ) {
l=0;
slot_fep(ue,
l,
subframe_rx<<1,
0,
0,
0);
}
pmch_flag = is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) ? 1 : 0;
if (do_pdcch_flag) {
......
......@@ -67,6 +67,11 @@ int ue_query_mch(module_id_t Mod_id, uint8_t CC_id, uint32_t frame,
sub_frame_t subframe, uint8_t eNB_index,
uint8_t * sync_area, uint8_t * mcch_active){ return(0);}
int ue_query_mch_fembms(module_id_t Mod_id, uint8_t CC_id, uint32_t frame,
sub_frame_t subframe, uint8_t eNB_index,
uint8_t * sync_area, uint8_t * mcch_active){ return(0);}
void dl_phy_sync_success(module_id_t module_idP,
frame_t frameP,
unsigned char eNB_index, uint8_t first_sync){}
......
This diff is collapsed.
......@@ -115,6 +115,11 @@ int ue_query_mch(module_id_t Mod_id, uint8_t CC_id, uint32_t frame,
sub_frame_t subframe, uint8_t eNB_index,
uint8_t * sync_area, uint8_t * mcch_active){ return(0);}
int ue_query_mch_fembms(module_id_t Mod_id, uint8_t CC_id, uint32_t frame,
sub_frame_t subframe, uint8_t eNB_index,
uint8_t * sync_area, uint8_t * mcch_active){ return(0);}
void dl_phy_sync_success(module_id_t module_idP,
frame_t frameP,
unsigned char eNB_index, uint8_t first_sync){}
......
......@@ -50,6 +50,7 @@ MESSAGE_DEF(M2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, m2ap_der
/* M2AP -> SCTP */
MESSAGE_DEF(M2AP_MCE_SCTP_REQ , MESSAGE_PRIORITY_MED, m2ap_mce_sctp_req_t , m2ap_mce_sctp_req)
MESSAGE_DEF(M2AP_ENB_SCTP_REQ , MESSAGE_PRIORITY_MED, m2ap_enb_sctp_req_t , m2ap_enb_sctp_req)
//MESSAGE_DEF(M2AP_ENB_SCTP_REQ , MESSAGE_PRIORITY_MED, m2ap_enb_setup_req_t , f1ap_enb_setup_req)
/* eNB_DU application layer -> M2AP messages or CU M2AP -> RRC*/
......
......@@ -480,7 +480,7 @@ typedef struct m2ap_mbms_scheduling_information_s {
uint8_t common_sf_allocation_period;
uint8_t mbms_area_id;
struct{
uint8_t allocated_sf_end;
uint16_t allocated_sf_end;
uint8_t data_mcs;
uint8_t mch_scheduling_period;
struct{
......@@ -533,6 +533,15 @@ typedef struct m2ap_mce_sctp_req_s {
uint32_t mce_port_for_M2C;
}m2ap_mce_sctp_req_t;
typedef struct m2ap_enb_sctp_req_s {
/* The local MCE IP address to bind */
net_ip_address_t enb_m2_ip_address;
/* eNB port for M2C*/
uint32_t enb_port_for_M2C;
}m2ap_enb_sctp_req_t;
typedef struct m2ap_mbms_scheduling_information_resp_s {
} m2ap_mbms_scheduling_information_resp_t;
typedef struct m2ap_session_start_req_s {
......
......@@ -214,7 +214,7 @@ void *eNB_app_task(void *args_p) {
long x2_enb_register_retry_timer_id;
uint32_t m2_register_enb_pending = 0;
uint32_t m2_registered_enb = 0;
long m2_enb_register_retry_timer_id;
//long m2_enb_register_retry_timer_id;
MessageDef *msg_p = NULL;
instance_t instance;
int result;
......@@ -236,16 +236,11 @@ void *eNB_app_task(void *args_p) {
/* Try to register each eNB with MCE each other */
if (is_m2ap_eNB_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) {
//eNB_app_register_MBMS_STA(RC.rrc[0]->node_type, enb_id_start, enb_id_end);
//m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end);
m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end);
if (timer_setup (5, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
NULL, &m2_enb_register_retry_timer_id) < 0) {
//LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");
//sleep(ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
//registered_enb = 0;
//register_enb_pending = eNB_app_register (RC.rrc[0]->node_type,enb_id_start, enb_id_end);
}
//if (timer_setup (5, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
// NULL, &m2_enb_register_retry_timer_id) < 0) {
//}
}
......@@ -376,11 +371,11 @@ void *eNB_app_task(void *args_p) {
}
} /* if (EPC_MODE_ENABLED) */
if(TIMER_HAS_EXPIRED (msg_p).timer_id == m2_enb_register_retry_timer_id) {
LOG_I(ENB_APP, " Received %s: timer_id %ld M2 register\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end);
}
// if(TIMER_HAS_EXPIRED (msg_p).timer_id == m2_enb_register_retry_timer_id) {
//
// LOG_I(ENB_APP, " Received %s: timer_id %ld M2 register\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
// m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end);
// }
break;
......
......@@ -3052,7 +3052,8 @@ void configure_du_mac(int inst) {
(LTE_SchedulingInfo_MBMS_r14_t *) NULL,
(struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
(LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
(LTE_MBSFN_AreaInfoList_r9_t *) NULL
(LTE_MBSFN_AreaInfoList_r9_t *) NULL,
(LTE_MBSFNAreaConfiguration_r9_t*) NULL
);
}
......
......@@ -306,7 +306,8 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance,
(LTE_SchedulingInfo_MBMS_r14_t *) NULL,
(struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
(LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
(LTE_MBSFN_AreaInfoList_r9_t *) NULL
(LTE_MBSFN_AreaInfoList_r9_t *) NULL,
(LTE_MBSFNAreaConfiguration_r9_t*) NULL
);
break;
} // case
......@@ -480,7 +481,8 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance,
(LTE_SchedulingInfo_MBMS_r14_t *) NULL,
(struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
(LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
(LTE_MBSFN_AreaInfoList_r9_t *) NULL
(LTE_MBSFN_AreaInfoList_r9_t *) NULL,
(LTE_MBSFNAreaConfiguration_r9_t*) NULL
);
}
......
......@@ -660,7 +660,7 @@ config_sib2_mbsfn_part( int Mod_idP,
if (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {
phycfg.cfg->embms_mbsfn_config.fourframes_flag[i] = 0;
phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i] = mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration
LOG_I (MAC, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i, phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i]);
LOG_I (MAC, "[CONFIG] MBSFN_SubframeConfig[%d] oneFrame pattern is %d\n", i, phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i]);
} else if (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration
phycfg.cfg->embms_mbsfn_config.fourframes_flag[i] = 1;
phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i] =
......@@ -668,7 +668,7 @@ config_sib2_mbsfn_part( int Mod_idP,
(mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)|
(mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]<<16);
LOG_I(MAC, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %x\n", i,
LOG_I(MAC, "[CONFIG] MBSFN_SubframeConfig[%d] fourFrame pattern is %x\n", i,
phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i]);
}
}
......@@ -777,7 +777,8 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP,
LTE_SchedulingInfo_MBMS_r14_t *schedulingInfo_fembms,
struct LTE_NonMBSFN_SubframeConfig_r14 *nonMBSFN_SubframeConfig,
LTE_SystemInformationBlockType1_MBMS_r14_t *sib1_mbms_r14_fembms,
LTE_MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList_fembms
LTE_MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList_fembms,
LTE_MBSFNAreaConfiguration_r9_t*mbms_AreaConfig
) {
int i;
int UE_id = -1;
......@@ -989,6 +990,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP,
cfg->num_tlv++;
//We need to reuse current MCH scheduler
//TOCHECK whether we can simply reuse current mbsfn_SubframeConfig stuff
RC.mac[Mod_idP]->common_channels[0].FeMBMS_flag = FeMBMS_Flag;
}
if (mbsfn_AreaInfoList != NULL) {
......@@ -1005,6 +1007,21 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP,
}
}
if(mbms_AreaConfig != NULL) {
RC.mac[Mod_idP]->common_channels[0].commonSF_AllocPeriod_r9 = mbms_AreaConfig->commonSF_AllocPeriod_r9;
LOG_I(MAC, "[eNB %d][CONFIG] LTE_MBSFNAreaConfiguration_r9_t(%p) commonSF_AllocPeriod_r9(%d)\n",Mod_idP,mbms_AreaConfig, RC.mac[Mod_idP]->common_channels[0].commonSF_AllocPeriod_r9);
for(i=0; i < mbms_AreaConfig->commonSF_Alloc_r9.list.count; i++){
RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i] = mbms_AreaConfig->commonSF_Alloc_r9.list.array[i];
LOG_I(RRC,"[eNB %d][CONFIG] MBSFNArea[%d] commonSF_Alloc_r9: radioframeAllocationPeriod(%ldn),radioframeAllocationOffset(%ld), subframeAllocation(%x,%x,%x)\n"
,Mod_idP,i
,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->radioframeAllocationPeriod
,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->radioframeAllocationOffset
,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[0]
,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[1]
,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[2]);
}
}
if (pmch_InfoList != NULL) {
// LOG_I(MAC,"DUY: lcid when entering rrc_mac config_req is %02d\n",(pmch_InfoList->list.array[0]->mbms_SessionInfoList_r9.list.array[0]->logicalChannelIdentity_r9));
LOG_I(MAC, "[CONFIG] Number of PMCH in this MBSFN Area %d\n",
......
......@@ -530,6 +530,7 @@ rrc_mac_config_req_ue(module_id_t Mod_idP,
LOG_I(MAC, "[UE %d] Configuring LTE_NonMBSFN \n",
Mod_idP);
phy_config_sib1_fembms_ue(Mod_idP, CC_idP, 0, nonMBSFN_SubframeConfig);
UE_mac_inst[Mod_idP].non_mbsfn_SubframeConfig = nonMBSFN_SubframeConfig;
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
......
......@@ -921,6 +921,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
}
#endif
int do_fembms_si=0;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
if (cc[CC_id].MBMS_flag > 0) {
start_meas(&RC.mac[module_idP]->schedule_mch);
......@@ -931,6 +932,10 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
}
stop_meas(&RC.mac[module_idP]->schedule_mch);
}
if (cc[CC_id].FeMBMS_flag > 0) {
do_fembms_si = 1;
}
}
static int debug_flag = 0;
......@@ -952,12 +957,22 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
}
/* This schedules MIB */
if ((subframeP == 0) && (frameP & 3) == 0)
schedule_mib(module_idP, frameP, subframeP);
if(!do_fembms_si/*get_softmodem_params()->fembms*/){
if ((subframeP == 0) && (frameP & 3) == 0)
schedule_mib(module_idP, frameP, subframeP);
}else{
if ((subframeP == 0) && (frameP & 15) == 0 ){
schedule_fembms_mib(module_idP, frameP, subframeP);
//schedule_SI_MBMS(module_idP, frameP, subframeP);
}
}
if (get_softmodem_params()->phy_test == 0) {
/* This schedules SI for legacy LTE and eMTC starting in subframeP */
schedule_SI(module_idP, frameP, subframeP);
if(!do_fembms_si/*get_softmodem_params()->fembms*/)
schedule_SI(module_idP, frameP, subframeP);
else
schedule_SI_MBMS(module_idP, frameP, subframeP);
/* This schedules Paging in subframeP */
schedule_PCH(module_idP,frameP,subframeP);
/* This schedules Random-Access for legacy LTE and eMTC starting in subframeP */
......
......@@ -731,6 +731,7 @@ schedule_SI_MBMS(module_id_t module_idP, frame_t frameP,
if (subframeP == 0) {
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
cc = &eNB->common_channels[CC_id];
//printf("*cc->sib1_MBMS->si_WindowLength_r14 %d \n", *cc->sib1_MBMS->si_WindowLength_r14);
vrb_map = (void *) &cc->vrb_map;
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
dl_config_request = &eNB->DL_req[CC_id];
......@@ -911,6 +912,64 @@ schedule_SI_MBMS(module_id_t module_idP, frame_t frameP,
stop_meas(&eNB->schedule_si_mbms);
}
void
schedule_fembms_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
eNB_MAC_INST *eNB = RC.mac[module_idP];
COMMON_channels_t *cc;
nfapi_dl_config_request_pdu_t *dl_config_pdu;
nfapi_tx_request_pdu_t *TX_req;
int mib_sdu_length;
int CC_id;
nfapi_dl_config_request_t *dl_config_request;
nfapi_dl_config_request_body_t *dl_req;
uint16_t sfn_sf = frameP << 4 | subframeP;
AssertFatal(subframeP == 0, "Subframe must be 0\n");
AssertFatal((frameP & 15) == 0, "Frame must be a multiple of 16\n");
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
dl_config_request = &eNB->DL_req[CC_id];
dl_req = &dl_config_request->dl_config_request_body;
cc = &eNB->common_channels[CC_id];
mib_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MIBCH_MBMS, 0xFFFF, 1, &cc->MIB_pdu.payload[0], 0); // not used in this case
LOG_D(MAC, "Frame %d, subframe %d: BCH PDU length %d\n", frameP, subframeP, mib_sdu_length);
if (mib_sdu_length > 0) {
LOG_D(MAC, "Frame %d, subframe %d: Adding BCH PDU in position %d (length %d)\n", frameP, subframeP, dl_req->number_pdu, mib_sdu_length);
if ((frameP & 1023) < 40)
LOG_D(MAC,
"[eNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes (cc->mib->message.schedulingInfoSIB1_BR_r13 %d)\n",
module_idP, frameP, CC_id, mib_sdu_length,
(int) cc->mib->message.schedulingInfoSIB1_BR_r13);
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_BCH_PDU_TYPE, dl_config_pdu->pdu_size =
2 + sizeof(nfapi_dl_config_bch_pdu);
dl_config_pdu->bch_pdu.bch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG;
dl_config_pdu->bch_pdu.bch_pdu_rel8.length = mib_sdu_length;
dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->bch_pdu.bch_pdu_rel8.transmission_power = 6000;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
dl_req->number_pdu++;
dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST;
dl_config_request->sfn_sf = sfn_sf;
LOG_D(MAC, "eNB->DL_req[0].number_pdu %d (%p)\n", dl_req->number_pdu, &dl_req->number_pdu);
// DL request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = 3;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = 3;
TX_req->segments[0].segment_data = cc[CC_id].MIB_pdu.payload;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
}
}
}
void
schedule_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
......
This diff is collapsed.
......@@ -56,6 +56,7 @@
#include "LTE_MobilityControlInfo.h"
#include "LTE_MBSFN-AreaInfoList-r9.h"
#include "LTE_MBSFN-SubframeConfigList.h"
#include "LTE_MBSFNAreaConfiguration-r9.h"
#include "LTE_PMCH-InfoList-r9.h"
#include "LTE_SCellToAddMod-r10.h"
#include "LTE_SystemInformationBlockType1-v1310-IEs.h"
......@@ -409,9 +410,11 @@ typedef struct {
/*!\brief Values of BCCH SIB_BR logical channel (fake) */
#define BCCH_SI_BR 7 // SI-BR
/*!\brief Values of BCCH SIB1_MBMS logical channel (fake) */
#define BCCH_SIB1_MBMS 60 // SIB1_MBMS //TODO better armonize index
#define MIBCH_MBMS 10 // SIB1_MBMS //TODO better armonize index
#define BCCH_SIB1_MBMS 12 // SIB1_MBMS //TODO better armonize index
/*!\brief Values of BCCH SI_MBMS logical channel (fake) */
#define BCCH_SI_MBMS 61 // SIB_MBMS //TODO better armonize index
#define BCCH_SI_MBMS 13 // SIB_MBMS //TODO better armonize index
#define MCCH_COUNTING 14
/*!\brief Value of CCCH / SRB0 logical channel */
#define CCCH 0 // srb0
/*!\brief DCCH / SRB1 logical channel */
......@@ -1286,6 +1289,8 @@ typedef struct {
/// MBSFN SubframeConfig
struct LTE_MBSFN_SubframeConfig *mbsfn_SubframeConfig[8];
struct LTE_NonMBSFN_SubframeConfig_r14 *non_mbsfn_SubframeConfig;
struct LTE_MBSFN_SubframeConfig *commonSF_Alloc_r9_mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA?
uint8_t commonSF_AllocPeriod_r9;
/// number of subframe allocation pattern available for MBSFN sync area
uint8_t num_sf_allocation_pattern;
/// MBMS Flag
......
......@@ -33,6 +33,16 @@
#include "PHY/defs_common.h" // for PRACH_RESOURCES_t and lte_subframe_t
#include "openair2/COMMON/mac_messages_types.h"
/** \fn void schedule_fembms_mib(module_id_t module_idP,frame_t frameP,sub_frame_t subframe);
\brief MIB scheduling for PBCH. This function requests the MIB from RRC and provides it to L1.
@param Mod_id Instance ID of eNB
@param frame Frame index
@param subframe Subframe number on which to act
*/
void schedule_fembms_mib(module_id_t module_idP,
frame_t frameP, sub_frame_t subframeP);
/** \addtogroup _mac
* @{
......@@ -532,6 +542,10 @@ int ue_query_mch(module_id_t Mod_id, uint8_t CC_id, uint32_t frame,
sub_frame_t subframe, uint8_t eNB_index,
uint8_t *sync_area, uint8_t *mcch_active);
int ue_query_mch_fembms(module_id_t Mod_id, uint8_t CC_id, uint32_t frame,
sub_frame_t subframe, uint8_t eNB_index,
uint8_t * sync_area, uint8_t * mcch_active);
/* \brief Called by PHY to get sdu for PUSCH transmission. It performs the following operations: Checks BSR for DCCH, DCCH1 and DTCH corresponding to previous values computed either in SR or BSR procedures. It gets rlc status indications on DCCH,DCCH1 and DTCH and forms BSR elements and PHR in MAC header. CRNTI element is not supported yet. It computes transport block for up to 3 SDUs and generates header and forms the complete MAC SDU.
@param Mod_id Instance id of UE in machine
......@@ -899,6 +913,7 @@ int generate_dlsch_header(unsigned char *mac_header,
@param non_MBSFN_SubframeConfig pointer to FeMBMS Non MBSFN Subframe Config
@param sib1_mbms_r14_fembms pointer SI Scheduling infomration for SI-MBMS
@param mbsfn_AreaInfoList_fembms pointer to FeMBMS MBSFN Area Info list from SIB1-MBMS
@param mbms_AreaConfiguration pointer to eMBMS MBSFN Area Configuration
*/
int rrc_mac_config_req_eNB(module_id_t module_idP,
......@@ -935,7 +950,8 @@ int rrc_mac_config_req_eNB(module_id_t module_idP,
LTE_SchedulingInfo_MBMS_r14_t *schedulingInfo_fembms,
struct LTE_NonMBSFN_SubframeConfig_r14 *nonMBSFN_SubframeConfig,
LTE_SystemInformationBlockType1_MBMS_r14_t *sib1_mbms_r14_fembms,
LTE_MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList_fembms
LTE_MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList_fembms,
LTE_MBSFNAreaConfiguration_r9_t * mbms_AreaConfiguration
);
/** \brief RRC eNB Configuration primitive for PHY/MAC. Allows configuration of PHY/MAC resources based on System Information (SI), RRCConnectionSetup and RRCConnectionReconfiguration messages.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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