diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab new file mode 100644 index 0000000000000000000000000000000000000000..e638836bb0cc652d3eb16bdb11468451a4d950f4 --- /dev/null +++ b/ci-scripts/Jenkinsfile-gitlab @@ -0,0 +1,180 @@ +// Comments + +pipeline { + agent { + label 'bellatrix' + } + options { + disableConcurrentBuilds() + timestamps() + gitLabConnection('OAI GitLab') + gitlabBuilds(builds: ["Build eNb-USRP", "Build gNb-usrp", "Build nr-UE-usrp", "Build phy-sim", "Analysis with cppcheck"]) + } + + stages { + stage ("Verify Guidelines") { + steps { + echo "Git URL is ${GIT_URL}" + echo "GitLab Act is ${env.gitlabActionType}" + script { + if ("MERGE".equals(env.gitlabActionType)) { + // GitLab-Jenkins plugin integration is lacking to perform the merge by itself + // Doing it manually --> it may have merge conflicts + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" + sh "zip -r -qq localZip.zip ." + + // Running astyle options on the list of modified files by the merge request + // For the moment, there is no fail criteria. Just a notification of number of files that do not follow + sh "./ci-scripts/checkCodingFormattingRules.sh --src-branch ${env.gitlabSourceBranch} --target-branch ${env.gitlabTargetBranch}" + def res=readFile('./oai_rules_result.txt').trim(); + if ("0".equals(res)) { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): All Changed files in Merge Request follow OAI Formatting Rules" + addGitLabMRComment comment: message + } else { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Some Changed files in Merge Request DO NOT follow OAI Formatting Rules" + addGitLabMRComment comment: message + } + } else { + echo "Git Branch is ${GIT_BRANCH}" + echo "Git Commit is ${GIT_COMMIT}" + + sh "zip -r -qq localZip.zip ." + // Running astyle options on all C/H files in the repository + // For the moment, there is no fail criteria. Just a notification of number of files that do not follow + sh "./ci-scripts/checkCodingFormattingRules.sh" + } + } + } + } + + stage ("Start VM -- cppcheck") { + steps { + sh "./ci-scripts/createVM.sh --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + + stage ("Start VM -- enb-usrp") { + steps { + sh "./ci-scripts/createVM.sh --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + + stage ("Start VM -- phy-sim") { + steps { + sh "./ci-scripts/createVM.sh --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + + stage ("Start VM -- gnb-usrp") { + steps { + sh "./ci-scripts/createVM.sh --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + + stage ("Start VM -- nu-ue-usrp") { + steps { + sh "./ci-scripts/createVM.sh --variant nu-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + + stage ("Variant Builds") { + parallel { + stage ("Analysis with cppcheck") { + steps { + gitlabCommitStatus(name: "Analysis with cppcheck") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + stage ("Build eNb-USRP") { + steps { + gitlabCommitStatus(name: "Build eNb-USRP") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + stage ("Build 5G gNB-USRP") { + steps { + gitlabCommitStatus(name: "Build gNb-usrp") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + stage ("Build 5G NR-UE-USRP") { + steps { + gitlabCommitStatus(name: "Build nr-UE-usrp") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant nu-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + stage ("Build physical simulators") { + steps { + gitlabCommitStatus(name: "Build phy-sim") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + } + post { + always { + script { + dir ('archives') { + sh "zip -r -qq vm_build_logs.zip enb_usrp phy_sim cppcheck gnb_usrp nrue_usrp" + } + if(fileExists('archives/vm_build_logs.zip')) { + archiveArtifacts artifacts: 'archives/vm_build_logs.zip' + } + if ("MERGE".equals(env.gitlabActionType)) { + sh "./ci-scripts/reportBuildLocally.sh --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger merge-request --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" + } else { + sh "./ci-scripts/reportBuildLocally.sh --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger push --branch ${GIT_BRANCH} --commit ${GIT_COMMIT}" + } + if(fileExists('build_results.html')) { + archiveArtifacts artifacts: 'build_results.html' + } + } + } + } + } + + stage ("Destroy all Virtual Machines") { + steps { + sh "./ci-scripts/destroyAllRunningVM.sh --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + } + post { + always { + script { + // Stage destroy may not be run if error in previous stage + sh "./ci-scripts/destroyAllRunningVM.sh --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + success { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + def message2 = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ") -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")" + slackSend channel: 'ci-enb', color: 'good', message: message2 + } else { + slackSend channel: 'ci-enb', color: 'good', message: message + } + } + } + failure { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + def message2 = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ") -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")" + slackSend channel: 'ci-enb', color: 'danger', message: message2 + } else { + slackSend channel: 'ci-enb', color: 'danger', message: message + } + } + } + } +} diff --git a/ci-scripts/astyle-options.txt b/ci-scripts/astyle-options.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f28bbb1f01d0a7c3bcae4c6614d9a38ed5a5db1 --- /dev/null +++ b/ci-scripts/astyle-options.txt @@ -0,0 +1,20 @@ +# OAI is using a style that is similar to the Google style +--style=google +# long options can be written without the preceding '--' +# Convert tabs to spaces +convert-tabs +# Indentation is 2 spaces +indent=spaces=2 +# Indent 'switch' blocks so that the 'case X:' statements are indented in the switch block. +indent-switches +# Indent C++ comments beginning in column one. +indent-col1-comments +# Pad empty lines around header blocks +break-blocks +delete-empty-lines +# Attach a pointer or reference operator (*, &, or ^) to the variable name (right) +align-pointer=name +# The code line length is 200 characters/columns +max-code-length=200 +break-after-logical +lineend=linux diff --git a/ci-scripts/buildLocally.sh b/ci-scripts/buildLocally.sh new file mode 100755 index 0000000000000000000000000000000000000000..67019508327a32e2cdf00c7f17d24c24d6918879 --- /dev/null +++ b/ci-scripts/buildLocally.sh @@ -0,0 +1,153 @@ +#!/bin/bash + +function usage { + echo "OAI Local Build Check script" + echo " Original Author: Raphael Defosseux" + echo "" + echo "Usage:" + echo "------" + echo " buildLocally.sh [OPTIONS]" + echo "" + echo "Options:" + echo "--------" + echo " --workspace #### OR -ws ####" + echo " Specify the workspace" + echo "" + echo " --help OR -h" + echo " Print this help message." + echo "" +} + +if [ $# -ne 2 ] && [ $# -ne 1 ] +then + echo "Syntax Error: not the correct number of arguments" + echo "" + usage + exit 1 +fi + +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + shift + usage + exit 0 + ;; + -ws|--workspace) + JENKINS_WKSP="$2" + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 +esac +done + +cd $JENKINS_WKSP +STATUS=0 + +############################################################ +# Creating a tmp folder to store results and artifacts +############################################################ +if [ ! -d $JENKINS_WKSP/archives ] +then + mkdir $JENKINS_WKSP/archives +fi + +source oaienv +cd $JENKINS_WKSP/cmake_targets + +############################################################ +# Building eNb with USRP option +############################################################ +ARCHIVES_LOC=$JENKINS_WKSP/archives/enb_usrp +if [ ! -d $ARCHIVES_LOC ] +then + mkdir $ARCHIVES_LOC +fi +./build_oai --eNB -w USRP -c + +# Generated log files: +if [ -f $JENKINS_WKSP/cmake_targets/log/lte-softmodem.Rel14.txt ] +then + LOCAL_STAT=`egrep -c "Built target lte-softmodem" $JENKINS_WKSP/cmake_targets/log/lte-softmodem.Rel14.txt` + if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi + cp $JENKINS_WKSP/cmake_targets/log/lte-softmodem.Rel14.txt $ARCHIVES_LOC +else + STATUS=-1 +fi +if [ -f $JENKINS_WKSP/cmake_targets/log/params_libconfig.Rel14.txt ] +then + LOCAL_STAT=`egrep -c "Built target params_libconfig" $JENKINS_WKSP/cmake_targets/log/params_libconfig.Rel14.txt` + if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi + cp $JENKINS_WKSP/cmake_targets/log/params_libconfig.Rel14.txt $ARCHIVES_LOC +else + STATUS=-1 +fi +if [ -f $JENKINS_WKSP/cmake_targets/log/coding.Rel14.txt ] +then + LOCAL_STAT=`egrep -c "Built target coding" $JENKINS_WKSP/cmake_targets/log/coding.Rel14.txt` + if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi + cp $JENKINS_WKSP/cmake_targets/log/coding.Rel14.txt $ARCHIVES_LOC +else + STATUS=-1 +fi +if [ -f $JENKINS_WKSP/cmake_targets/log/oai_usrpdevif.Rel14.txt ] +then + LOCAL_STAT=`egrep -c "Built target oai_usrpdevif" $JENKINS_WKSP/cmake_targets/log/oai_usrpdevif.Rel14.txt` + if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi + cp $JENKINS_WKSP/cmake_targets/log/oai_usrpdevif.Rel14.txt $ARCHIVES_LOC +else + STATUS=-1 +fi + +############################################################ +# Building basic simulator +############################################################ +ARCHIVES_LOC=$JENKINS_WKSP/archives/basic_sim +if [ ! -d $ARCHIVES_LOC ] +then + mkdir $ARCHIVES_LOC +fi +cd $JENKINS_WKSP/cmake_targets +./build_oai --basic-simulator -c + +# Generated log files: +if [ -f $JENKINS_WKSP/cmake_targets/log/basic_simulator_enb.txt ] +then + LOCAL_STAT=`egrep -c "Built target lte-softmodem" $JENKINS_WKSP/cmake_targets/log/basic_simulator_enb.txt` + if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi + cp $JENKINS_WKSP/cmake_targets/log/basic_simulator_enb.txt $ARCHIVES_LOC +else + STATUS=-1 +fi +if [ -f $JENKINS_WKSP/cmake_targets/log/basic_simulator_ue.txt ] +then + LOCAL_STAT=`egrep -c "Built target lte-uesoftmodem" $JENKINS_WKSP/cmake_targets/log/basic_simulator_ue.txt` + if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi + cp $JENKINS_WKSP/cmake_targets/log/basic_simulator_ue.txt $ARCHIVES_LOC +else + STATUS=-1 +fi +if [ -f $JENKINS_WKSP/cmake_targets/log/conf2uedata.Rel14.txt ] +then + LOCAL_STAT=`egrep -c "Built target conf2uedata" $JENKINS_WKSP/cmake_targets/log/conf2uedata.Rel14.txt` + if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi + cp $JENKINS_WKSP/cmake_targets/log/conf2uedata.Rel14.txt $ARCHIVES_LOC +else + STATUS=-1 +fi + +############################################################ +# Creating a zip for Jenkins archiving +############################################################ +cd $JENKINS_WKSP/archives/ +zip -r local_build_logs.zip basic_sim enb_usrp + +exit $STATUS diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh new file mode 100755 index 0000000000000000000000000000000000000000..8228b7241b6f7d5129680bf82b67e4aa2c4967f7 --- /dev/null +++ b/ci-scripts/buildOnVM.sh @@ -0,0 +1,403 @@ +#!/bin/bash + +function usage { + echo "OAI VM Build Check script" + echo " Original Author: Raphael Defosseux" + echo " Requirements:" + echo " -- uvtool uvtool-libvirt apt-cacher" + echo " -- xenial image already synced" + echo " Default:" + echo " -- eNB with USRP" + echo "" + echo "Usage:" + echo "------" + echo " buildOnVM.sh [OPTIONS]" + echo "" + echo "Options:" + echo "--------" + echo " --job-name #### OR -jn ####" + echo " Specify the name of the Jenkins job." + echo "" + echo " --build-id #### OR -id ####" + echo " Specify the build ID of the Jenkins job." + echo "" + echo " --workspace #### OR -ws ####" + echo " Specify the workspace." + echo "" + echo " --variant enb-usrp OR -v1" + echo " --variant basic-sim OR -v2" + echo " --variant phy-sim OR -v3" + echo " --variant cppcheck OR -v4" + echo " --variant gnb-usrp OR -v5" + echo " --variant nu-ue-usrp OR -v6" + echo " --variant enb-ethernet OR -v7" + echo " --variant ue-ethernet OR -v8" + echo " Specify the variant to build." + echo "" + echo " --keep-vm-alive OR -k" + echo " Keep the VM alive after the build." + echo "" + echo " --help OR -h" + echo " Print this help message." + echo "" +} + +function variant_usage { + echo "OAI VM Build Check script" + echo " Original Author: Raphael Defosseux" + echo "" + echo " --variant enb-usrp OR -v1" + echo " --variant basic-sim OR -v2" + echo " --variant phy-sim OR -v3" + echo " --variant cppcheck OR -v4" + echo " --variant gnb-usrp OR -v5" + echo " --variant nu-ue-usrp OR -v6" + echo " --variant enb-ethernet OR -v7" + echo " --variant ue-ethernet OR -v8" + echo "" +} + +if [ $# -lt 1 ] || [ $# -gt 9 ] +then + echo "Syntax Error: not the correct number of arguments" + echo "" + usage + exit 1 +fi + +VM_TEMPLATE=ci- +JOB_NAME=XX +BUILD_ID=XX +VM_NAME=ci-enb-usrp +ARCHIVES_LOC=enb_usrp +LOG_PATTERN=.Rel14.txt +NB_PATTERN_FILES=4 +BUILD_OPTIONS="--eNB -w USRP" +KEEP_VM_ALIVE=0 + +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + shift + usage + exit 0 + ;; + -jn|--job-name) + JOB_NAME="$2" + shift + shift + ;; + -id|--build-id) + BUILD_ID="$2" + shift + shift + ;; + -ws|--workspace) + JENKINS_WKSP="$2" + shift + shift + ;; + -k|--keep-vm-alive) + KEEP_VM_ALIVE=1 + shift + ;; + -v1) + VM_NAME=ci-enb-usrp + ARCHIVES_LOC=enb_usrp + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=4 + BUILD_OPTIONS="--eNB -w USRP" + shift + ;; + -v2) + VM_NAME=ci-basic-sim + ARCHIVES_LOC=basic_sim + LOG_PATTERN=basic_simulator + NB_PATTERN_FILES=2 + BUILD_OPTIONS="--basic-simulator" + shift + ;; + -v3) + VM_NAME=ci-phy-sim + ARCHIVES_LOC=phy_sim + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=3 + BUILD_OPTIONS="--phy_simulators" + shift + ;; + -v4) + VM_NAME=ci-cppcheck + ARCHIVES_LOC=cppcheck + LOG_PATTERN=cppcheck.xml + NB_PATTERN_FILES=1 + BUILD_OPTIONS="--enable=warning --force --xml --xml-version=2" + shift + ;; + -v5) + VM_NAME=ci-gnb-usrp + ARCHIVES_LOC=gnb_usrp + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=4 + BUILD_OPTIONS="--gNB -w USRP" + shift + ;; + -v6) + VM_NAME=ci-ue-nr-usrp + ARCHIVES_LOC=nrue_usrp + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=4 + BUILD_OPTIONS="--nrUE -w USRP" + shift + ;; + -v7) + VM_NAME=ci-enb-ethernet + ARCHIVES_LOC=enb_eth + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=6 + BUILD_OPTIONS="--eNB -t ETHERNET --noS1" + shift + ;; + -v8) + VM_NAME=ci-ue-ethernet + ARCHIVES_LOC=ue_eth + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=6 + BUILD_OPTIONS="--UE -t ETHERNET --noS1" + shift + ;; + --variant) + variant="$2" + case $variant in + enb-usrp) + VM_NAME=ci-enb-usrp + ARCHIVES_LOC=enb_usrp + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=4 + BUILD_OPTIONS="--eNB -w USRP" + ;; + basic-sim) + VM_NAME=ci-basic-sim + ARCHIVES_LOC=basic_sim + LOG_PATTERN=basic_simulator + NB_PATTERN_FILES=2 + BUILD_OPTIONS="--basic-simulator" + ;; + phy-sim) + VM_NAME=ci-phy-sim + ARCHIVES_LOC=phy_sim + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=3 + BUILD_OPTIONS="--phy_simulators" + ;; + cppcheck) + VM_NAME=ci-cppcheck + ARCHIVES_LOC=cppcheck + LOG_PATTERN=cppcheck.xml + NB_PATTERN_FILES=1 + BUILD_OPTIONS="--enable=warning --force --xml --xml-version=2" + ;; + gnb-usrp) + VM_NAME=ci-gnb-usrp + ARCHIVES_LOC=gnb_usrp + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=4 + BUILD_OPTIONS="--gNB -w USRP" + ;; + nu-ue-usrp) + VM_NAME=ci-ue-nr-usrp + ARCHIVES_LOC=nrue_usrp + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=4 + BUILD_OPTIONS="--nrUE -w USRP" + ;; + enb-ethernet) + VM_NAME=ci-enb-ethernet + ARCHIVES_LOC=enb_eth + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=6 + BUILD_OPTIONS="--eNB -t ETHERNET --noS1" + ;; + ue-ethernet) + VM_NAME=ci-ue-ethernet + ARCHIVES_LOC=ue_eth + LOG_PATTERN=.Rel14.txt + NB_PATTERN_FILES=6 + BUILD_OPTIONS="--UE -t ETHERNET --noS1" + ;; + *) + echo "" + echo "Syntax Error: Invalid Variant option -> $variant" + echo "" + variant_usage + exit 1 + esac + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 +esac +done + +if [ ! -f $JENKINS_WKSP/localZip.zip ] +then + echo "Missing localZip.zip file!" + exit 1 +fi +if [ ! -f /etc/apt/apt.conf.d/01proxy ] +then + echo "Missing /etc/apt/apt.conf.d/01proxy file!" + echo "Is apt-cacher installed and configured?" + exit 1 +fi + +if [ "$JOB_NAME" == "XX" ] || [ "$BUILD_ID" == "XX" ] +then + VM_TEMPLATE=ci- +else + VM_TEMPLATE=${JOB_NAME}-b${BUILD_ID}- +fi + +VM_NAME=`echo $VM_NAME | sed -e "s#ci-#$VM_TEMPLATE#"` +VM_CMDS=${VM_NAME}_cmds.txt +ARCHIVES_LOC=${JENKINS_WKSP}/archives/${ARCHIVES_LOC} + +echo "VM_NAME = $VM_NAME" +echo "VM_CMD_FILE = $VM_CMDS" +echo "JENKINS_WKSP = $JENKINS_WKSP" +echo "ARCHIVES_LOC = $ARCHIVES_LOC" +echo "BUILD_OPTIONS = $BUILD_OPTIONS" + +IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME` + +if [ $IS_VM_ALIVE -eq 0 ] +then + echo "############################################################" + echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" + echo "############################################################" + uvt-kvm create $VM_NAME release=xenial --memory 2048 --cpu 4 --unsafe-caching --template ci-scripts/template-host.xml +fi + +echo "Waiting for VM to be started" +uvt-kvm wait $VM_NAME --insecure + +VM_IP_ADDR=`uvt-kvm ip $VM_NAME` +echo "$VM_NAME has for IP addr = $VM_IP_ADDR" + +echo "############################################################" +echo "Copying GIT repo into VM ($VM_NAME)" +echo "############################################################" +scp -o StrictHostKeyChecking=no localZip.zip ubuntu@$VM_IP_ADDR:/home/ubuntu +scp -o StrictHostKeyChecking=no /etc/apt/apt.conf.d/01proxy ubuntu@$VM_IP_ADDR:/home/ubuntu + +echo "############################################################" +echo "Running install and build script on VM ($VM_NAME)" +echo "############################################################" +echo "sudo cp 01proxy /etc/apt/apt.conf.d/" > $VM_CMDS +if [[ "$VM_NAME" == *"-cppcheck"* ]] +then + echo "echo \"sudo apt-get --yes --quiet install zip cppcheck \"" >> $VM_CMDS + echo "sudo apt-get update > zip-install.txt 2>&1" >> $VM_CMDS + echo "sudo apt-get --yes install zip cppcheck >> zip-install.txt 2>&1" >> $VM_CMDS +else + echo "echo \"sudo apt-get --yes --quiet install zip subversion libboost-dev \"" >> $VM_CMDS + echo "sudo apt-get --yes install zip subversion libboost-dev > zip-install.txt 2>&1" >> $VM_CMDS +fi +echo "mkdir tmp" >> $VM_CMDS +echo "cd tmp" >> $VM_CMDS +echo "echo \"unzip -qq -DD ../localZip.zip\"" >> $VM_CMDS +echo "unzip -qq -DD ../localZip.zip" >> $VM_CMDS +if [[ "$VM_NAME" == *"-cppcheck"* ]] +then + echo "mkdir cmake_targets/log" >> $VM_CMDS + echo "cp /home/ubuntu/zip-install.txt cmake_targets/log" >> $VM_CMDS + echo "echo \"cppcheck $BUILD_OPTIONS . \"" >> $VM_CMDS + echo "cppcheck $BUILD_OPTIONS . 2> cmake_targets/log/cppcheck.xml 1> cmake_targets/log/cppcheck_build.txt" >> $VM_CMDS +else + echo "echo \"source oaienv\"" >> $VM_CMDS + echo "source oaienv" >> $VM_CMDS + echo "cd cmake_targets/" >> $VM_CMDS + echo "mkdir log" >> $VM_CMDS + echo "cp /home/ubuntu/zip-install.txt log" >> $VM_CMDS + echo "echo \"./build_oai -I $BUILD_OPTIONS \"" >> $VM_CMDS + echo "./build_oai -I $BUILD_OPTIONS > log/install-build.txt 2>&1" >> $VM_CMDS +fi +ssh -o StrictHostKeyChecking=no ubuntu@$VM_IP_ADDR < $VM_CMDS + +echo "############################################################" +echo "Creating a tmp folder to store results and artifacts" +echo "############################################################" +if [ ! -d $JENKINS_WKSP/archives ] +then + mkdir $JENKINS_WKSP/archives +fi + +if [ ! -d $ARCHIVES_LOC ] +then + mkdir $ARCHIVES_LOC +fi + +scp -o StrictHostKeyChecking=no ubuntu@$VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/*.txt $ARCHIVES_LOC +if [[ "$VM_NAME" == *"-cppcheck"* ]] +then + scp -o StrictHostKeyChecking=no ubuntu@$VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/*.xml $ARCHIVES_LOC +fi + +if [ $KEEP_VM_ALIVE -eq 0 ] +then + echo "############################################################" + echo "Destroying VM" + echo "############################################################" + uvt-kvm destroy $VM_NAME + ssh-keygen -R $VM_IP_ADDR +fi +rm -f $VM_CMDS + +echo "############################################################" +echo "Checking build status" +echo "############################################################" + +LOG_FILES=`ls $ARCHIVES_LOC/*.txt $ARCHIVES_LOC/*.xml` +STATUS=0 +NB_FOUND_FILES=0 + +for FULLFILE in $LOG_FILES +do + if [[ $FULLFILE == *"$LOG_PATTERN"* ]] + then + filename=$(basename -- "$FULLFILE") + if [ "$LOG_PATTERN" == ".Rel14.txt" ] + then + PASS_PATTERN=`echo $filename | sed -e "s#$LOG_PATTERN##"` + fi + if [ "$LOG_PATTERN" == "basic_simulator" ] + then + PASS_PATTERN="lte-" + fi + if [ "$LOG_PATTERN" == "cppcheck.xml" ] + then + PASS_PATTERN="results version" + LOCAL_STAT=`egrep -c "$PASS_PATTERN" $FULLFILE` + else + LOCAL_STAT=`egrep -c "Built target $PASS_PATTERN" $FULLFILE` + fi + if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi + NB_FOUND_FILES=$((NB_FOUND_FILES + 1)) + fi +done + +if [ $NB_PATTERN_FILES -ne $NB_FOUND_FILES ]; then STATUS=-1; fi + +if [ $STATUS -eq 0 ] +then + echo "STATUS seems OK" +else + echo "STATUS failed?" +fi +exit $STATUS diff --git a/ci-scripts/checkCodingFormattingRules.sh b/ci-scripts/checkCodingFormattingRules.sh new file mode 100755 index 0000000000000000000000000000000000000000..20657b7fd0ade53a3f4e67a5264e3a95fb545afa --- /dev/null +++ b/ci-scripts/checkCodingFormattingRules.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +function usage { + echo "OAI Coding / Formatting Guideline Check script" + echo " Original Author: Raphael Defosseux" + echo "" + echo " Requirement: astyle shall be installed" + echo "" + echo " By default (no options) the complete repository will be checked" + echo " In case of merge request, provided source and target branch," + echo " the script will check only the modified files" + echo "" + echo "Usage:" + echo "------" + echo " checkCodingFormattingRules.sh [OPTIONS]" + echo "" + echo "Options:" + echo "--------" + echo " --src-branch #### OR -sb ####" + echo " Specify the source branch of the merge request." + echo "" + echo " --target-branch #### OR -tb ####" + echo " Specify the target branch of the merge request (usually develop)." + echo "" + echo " --help OR -h" + echo " Print this help message." + echo "" +} + +if [ $# -ne 4 ] && [ $# -ne 1 ] && [ $# -ne 0 ] +then + echo "Syntax Error: not the correct number of arguments" + echo "" + usage + exit 1 +fi + +if [ $# -eq 0 ] +then + echo " ---- Checking the whole repository ----" + echo "" + NB_FILES_TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt --recursive *.c *.h | grep -c Formatted ` + echo "Nb Files that do NOT follow OAI rules: $NB_FILES_TO_FORMAT" + echo $NB_FILES_TO_FORMAT > ./oai_rules_result.txt + exit 0 +fi + +checker=0 +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + shift + usage + exit 0 + ;; + -sb|--src-branch) + SOURCE_BRANCH="$2" + let "checker|=0x1" + shift + shift + ;; + -tb|--target-branch) + TARGET_BRANCH="$2" + let "checker|=0x2" + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 +esac + +done + + +if [ $checker -ne 3 ] +then + echo "Source Branch is : $SOURCE_BRANCH" + echo "Target Branch is : $TARGET_BRANCH" + echo "" + echo "Syntax Error: missing option" + echo "" + usage + exit 1 +fi + +# Merge request scenario + +MERGE_COMMMIT=`git log -n1 | grep commit | sed -e "s@commit @@"` +TARGET_INIT_COMMIT=`cat .git/refs/remotes/origin/$TARGET_BRANCH` + +echo " ---- Checking the modified files by the merge request ----" +echo "" +echo "Source Branch is : $SOURCE_BRANCH" +echo "Target Branch is : $TARGET_BRANCH" +echo "Merged Commit is : $MERGE_COMMMIT" +echo "Target Init is : $TARGET_INIT_COMMIT" + +# Retrieve the list of modified files since the latest develop commit +MODIFIED_FILES=`git log $TARGET_INIT_COMMIT..$MERGE_COMMMIT --oneline --name-status | egrep "^M|^A" | sed -e "s@^M\t*@@" -e "s@^A\t*@@" | sort | uniq` +NB_TO_FORMAT=0 +for FULLFILE in $MODIFIED_FILES +do + echo $FULLFILE + filename=$(basename -- "$FULLFILE") + EXT="${filename##*.}" + if [ $EXT = "c" ] || [ $EXT = "h" ] || [ $EXT = "cpp" ] || [ $EXT = "hpp" ] + then + TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt $FULLFILE | grep -c Formatted ` + NB_TO_FORMAT=$((NB_TO_FORMAT + TO_FORMAT)) + fi +done +echo "Nb Files that do NOT follow OAI rules: $NB_TO_FORMAT" +echo $NB_TO_FORMAT > ./oai_rules_result.txt + +exit 0 diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh new file mode 100755 index 0000000000000000000000000000000000000000..7cb5647308358e5788661ac92b192901ffac6e1a --- /dev/null +++ b/ci-scripts/createVM.sh @@ -0,0 +1,185 @@ +#!/bin/bash + +function usage { + echo "OAI VM Creation script" + echo " Original Author: Raphael Defosseux" + echo " Requirements:" + echo " -- uvtool uvtool-libvirt apt-cacher" + echo " -- xenial image already synced" + echo " Default:" + echo " -- eNB with USRP" + echo "" + echo "Usage:" + echo "------" + echo " createVM.sh [OPTIONS]" + echo "" + echo "Options:" + echo "--------" + echo " --job-name #### OR -jn ####" + echo " Specify the name of the Jenkins job." + echo "" + echo " --build-id #### OR -id ####" + echo " Specify the build ID of the Jenkins job." + echo "" + echo " --variant enb-usrp OR -v1" + echo " --variant basic-sim OR -v2" + echo " --variant phy-sim OR -v3" + echo " --variant cppcheck OR -v4" + echo " --variant gnb-usrp OR -v5" + echo " --variant nu-ue-usrp OR -v6" + echo " --variant enb-ethernet OR -v7" + echo " --variant ue-ethernet OR -v8" + echo " Specify the variant to build." + echo "" + echo " --help OR -h" + echo " Print this help message." + echo "" +} + +function variant_usage { + echo "OAI VM Build Check script" + echo " Original Author: Raphael Defosseux" + echo "" + echo " --variant enb-usrp OR -v1" + echo " --variant basic-sim OR -v2" + echo " --variant phy-sim OR -v3" + echo " --variant cppcheck OR -v4" + echo " --variant gnb-usrp OR -v5" + echo " --variant nu-ue-usrp OR -v6" + echo " --variant enb-ethernet OR -v7" + echo " --variant ue-ethernet OR -v8" + echo "" +} + +if [ $# -lt 1 ] || [ $# -gt 6 ] +then + echo "Syntax Error: not the correct number of arguments" + echo "" + usage + exit 1 +fi + +VM_TEMPLATE=ci- +JOB_NAME=XX +BUILD_ID=XX +VM_NAME=ci-enb-usrp + +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + shift + usage + exit 0 + ;; + -jn|--job-name) + JOB_NAME="$2" + shift + shift + ;; + -id|--build-id) + BUILD_ID="$2" + shift + shift + ;; + -v1) + VM_NAME=ci-enb-usrp + shift + ;; + -v2) + VM_NAME=ci-basic-sim + shift + ;; + -v3) + VM_NAME=ci-phy-sim + shift + ;; + -v4) + VM_NAME=ci-cppcheck + shift + ;; + -v5) + VM_NAME=ci-gnb-usrp + shift + ;; + -v6) + VM_NAME=ci-ue-nr-usrp + shift + ;; + -v7) + VM_NAME=ci-enb-ethernet + shift + ;; + -v8) + VM_NAME=ci-ue-ethernet + shift + ;; + --variant) + variant="$2" + case $variant in + enb-usrp) + VM_NAME=ci-enb-usrp + ;; + basic-sim) + VM_NAME=ci-basic-sim + ;; + phy-sim) + VM_NAME=ci-phy-sim + ;; + cppcheck) + VM_NAME=ci-cppcheck + ;; + gnb-usrp) + VM_NAME=ci-gnb-usrp + ;; + nu-ue-usrp) + VM_NAME=ci-ue-nr-usrp + ;; + enb-ethernet) + VM_NAME=ci-enb-ethernet + ;; + ue-ethernet) + VM_NAME=ci-ue-ethernet + ;; + *) + echo "" + echo "Syntax Error: Invalid Variant option -> $variant" + echo "" + variant_usage + exit 1 + esac + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 +esac +done + +if [ "$JOB_NAME" == "XX" ] || [ "$BUILD_ID" == "XX" ] +then + VM_TEMPLATE=ci- +else + VM_TEMPLATE=${JOB_NAME}-b${BUILD_ID}- +fi + +VM_NAME=`echo $VM_NAME | sed -e "s#ci-#$VM_TEMPLATE#"` +VM_CMDS=${VM_NAME}_cmds.txt + +echo "VM_NAME = $VM_NAME" + +echo "############################################################" +echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" +echo "############################################################" +uvt-kvm create $VM_NAME release=xenial --memory 2048 --cpu 4 --unsafe-caching --template ci-scripts/template-host.xml +echo "Waiting for VM to be started" +uvt-kvm wait $VM_NAME --insecure + +VM_IP_ADDR=`uvt-kvm ip $VM_NAME` +echo "$VM_NAME has for IP addr = $VM_IP_ADDR" +exit 0 diff --git a/ci-scripts/destroyAllRunningVM.sh b/ci-scripts/destroyAllRunningVM.sh new file mode 100755 index 0000000000000000000000000000000000000000..c9eb43b4ef235d83a0803c9055c5cd772406d629 --- /dev/null +++ b/ci-scripts/destroyAllRunningVM.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +function usage { + echo "OAI VM Destroy script" + echo " Original Author: Raphael Defosseux" + echo "" + echo "Usage:" + echo "------" + echo " destroyAllRunningVM.sh [OPTIONS]" + echo "" + echo "Options:" + echo "--------" + echo " --job-name #### OR -jn ####" + echo " Specify the name of the Jenkins job." + echo "" + echo " --build-id #### OR -id ####" + echo " Specify the build ID of the Jenkins job." + echo "" + echo " --help OR -h" + echo " Print this help message." + echo "" +} + +if [ $# -gt 4 ] +then + echo "Syntax Error: not the correct number of arguments" + echo "" + usage + exit 1 +fi + +VM_TEMPLATE=ci- +JOB_NAME=XX +BUILD_ID=XX + +while [[ $# -gt 0 ]] +do +key="$1" +case $key in + -h|--help) + shift + usage + exit 0 + ;; + -jn|--job-name) + JOB_NAME="$2" + shift + shift + ;; + -id|--build-id) + BUILD_ID="$2" + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 +esac +done + +if [ "$JOB_NAME" == "XX" ] || [ "$BUILD_ID" == "XX" ] +then + VM_TEMPLATE=ci- +else + VM_TEMPLATE=${JOB_NAME}-b${BUILD_ID}- +fi + +LIST_CI_VM=`uvt-kvm list | grep $VM_TEMPLATE` + +for CI_VM in $LIST_CI_VM +do + VM_IP_ADDR=`uvt-kvm ip $CI_VM` + echo "VM to destroy: $CI_VM -- IP $VM_IP_ADDR" + uvt-kvm destroy $CI_VM + ssh-keygen -R $VM_IP_ADDR +done + +exit 0 + diff --git a/ci-scripts/doGitLabMerge.sh b/ci-scripts/doGitLabMerge.sh new file mode 100755 index 0000000000000000000000000000000000000000..cc6f38c81063b3f7dc370d428fe4f8205f4eb950 --- /dev/null +++ b/ci-scripts/doGitLabMerge.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +function usage { + echo "OAI GitLab merge request applying script" + echo " Original Author: Raphael Defosseux" + echo "" + echo "Usage:" + echo "------" + echo "" + echo " doGitLabMerge.sh [OPTIONS] [MANDATORY_OPTIONS]" + echo "" + echo "Mandatory Options:" + echo "------------------" + echo "" + echo " --src-branch #### OR -sb ####" + echo " Specify the source branch of the merge request." + echo "" + echo " --src-commit #### OR -sc ####" + echo " Specify the source commit ID (SHA-1) of the merge request." + echo "" + echo " --target-branch #### OR -tb ####" + echo " Specify the target branch of the merge request (usually develop)." + echo "" + echo " --target-commit #### OR -tc ####" + echo " Specify the target commit ID (SHA-1) of the merge request." + echo "" + echo "Options:" + echo "--------" + echo " --help OR -h" + echo " Print this help message." + echo "" +} + +if [ $# -ne 8 ] && [ $# -ne 1 ] +then + echo "Syntax Error: not the correct number of arguments" + echo "" + usage + exit 1 +fi + +checker=0 +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + shift + usage + exit 0 + ;; + -sb|--src-branch) + SOURCE_BRANCH="$2" + let "checker|=0x1" + shift + shift + ;; + -sc|--src-commit) + SOURCE_COMMIT_ID="$2" + let "checker|=0x2" + shift + shift + ;; + -tb|--target-branch) + TARGET_BRANCH="$2" + let "checker|=0x4" + shift + shift + ;; + -tc|--target-commit) + TARGET_COMMIT_ID="$2" + let "checker|=0x8" + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 +esac + +done + +echo "Source Branch is : $SOURCE_BRANCH" +echo "Source Commit ID is : $SOURCE_COMMIT_ID" +echo "Target Branch is : $TARGET_BRANCH" +echo "Target Commit ID is : $TARGET_COMMIT_ID" + +if [ $checker -ne 15 ] +then + echo "" + echo "Syntax Error: missing option" + echo "" + usage + exit 1 +fi + +git config user.email "jenkins@openairinterface.org" +git config user.name "OAI Jenkins" + +git checkout -f $SOURCE_COMMIT_ID + +git merge --ff $TARGET_COMMIT_ID -m "Temporary merge for CI" + +exit 0 + + diff --git a/ci-scripts/reportBuildLocally.sh b/ci-scripts/reportBuildLocally.sh new file mode 100755 index 0000000000000000000000000000000000000000..bd08d23e94e1a52d0ba6dbb4e1278bcf07f66c68 --- /dev/null +++ b/ci-scripts/reportBuildLocally.sh @@ -0,0 +1,594 @@ +#!/bin/bash + +function usage { + echo "OAI Local Build Report script" + echo " Original Author: Raphael Defosseux" + echo "" + echo "Usage:" + echo "------" + echo "" + echo " reportBuildLocally.sh [OPTIONS]" + echo "" + echo "Options:" + echo "--------" + echo "" + echo " --help OR -h" + echo " Print this help message." + echo "" + echo "Job Options:" + echo "------------" + echo "" + echo " --git-url #### OR -gu ####" + echo " Specify the URL of the GIT Repository." + echo "" + echo " --job-name #### OR -jn ####" + echo " Specify the name of the Jenkins job." + echo "" + echo " --build-id #### OR -id ####" + echo " Specify the build ID of the Jenkins job." + echo "" + echo " --trigger merge-request OR -mr" + echo " --trigger push OR -pu" + echo " Specify trigger action of the Jenkins job. Either a merge-request event or a push event." + echo "" + echo "Merge-Request Options:" + echo "----------------------" + echo "" + echo " --src-branch #### OR -sb ####" + echo " Specify the source branch of the merge request." + echo "" + echo " --src-commit #### OR -sc ####" + echo " Specify the source commit ID (SHA-1) of the merge request." + echo "" + echo " --target-branch #### OR -tb ####" + echo " Specify the target branch of the merge request (usually develop)." + echo "" + echo " --target-commit #### OR -tc ####" + echo " Specify the target commit ID (SHA-1) of the merge request." + echo "" + echo "Push Options:" + echo "----------------------" + echo "" + echo " --branch #### OR -br ####" + echo " Specify the branch of the push event." + echo "" + echo " --commit #### OR -co ####" + echo " Specify the commit ID (SHA-1) of the push event." + echo "" + echo "" +} + +function trigger_usage { + echo "OAI Local Build Report script" + echo " Original Author: Raphael Defosseux" + echo "" + echo " --trigger merge-request OR -mr" + echo " --trigger push OR -pu" + echo " Specify trigger action of the Jenkins job. Either a merge-request event or a push event." + echo "" +} + +function details_table { + echo " <h4>$1</h4>" >> $3 + + echo " <table border = \"1\">" >> $3 + echo " <tr bgcolor = \"#33CCFF\" >" >> $3 + echo " <th>File</th>" >> $3 + echo " <th>Line Number</th>" >> $3 + echo " <th>Status</th>" >> $3 + echo " <th>Message</th>" >> $3 + echo " </tr>" >> $3 + + LIST_MESSAGES=`egrep "error:|warning:" $2 | egrep -v "jobserver unavailable|Clock skew detected.|flexran.proto"` + COMPLETE_MESSAGE="start" + for MESSAGE in $LIST_MESSAGES + do + if [[ $MESSAGE == *"/home/ubuntu/tmp"* ]] + then + FILENAME=`echo $MESSAGE | sed -e "s#^/home/ubuntu/tmp/##" | awk -F ":" '{print $1}'` + LINENB=`echo $MESSAGE | awk -F ":" '{print $2}'` + if [ "$COMPLETE_MESSAGE" != "start" ] + then + COMPLETE_MESSAGE=`echo $COMPLETE_MESSAGE | sed -e "s#‘#'#g" -e "s#’#'#g"` + echo " <td>$COMPLETE_MESSAGE</td>" >> $3 + echo " </tr>" >> $3 + fi + echo " <tr>" >> $3 + echo " <td>$FILENAME</td>" >> $3 + echo " <td>$LINENB</td>" >> $3 + else + if [[ $MESSAGE == *"warning:"* ]] || [[ $MESSAGE == *"error:"* ]] + then + MSGTYPE=`echo $MESSAGE | sed -e "s#:##g"` + echo " <td>$MSGTYPE</td>" >> $3 + COMPLETE_MESSAGE="" + else + COMPLETE_MESSAGE=$COMPLETE_MESSAGE" "$MESSAGE + fi + fi + done + + if [ "$COMPLETE_MESSAGE" != "start" ] + then + COMPLETE_MESSAGE=`echo $COMPLETE_MESSAGE | sed -e "s#‘#'#g" -e "s#’#'#g"` + echo " <td>$COMPLETE_MESSAGE</td>" >> $3 + echo " </tr>" >> $3 + fi + echo " </table>" >> $3 +} + +function summary_table_header { + echo " <h3>$1</h3>" >> ./build_results.html + echo " <table border = \"1\">" >> ./build_results.html + echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html + echo " <th>Element</th>" >> ./build_results.html + echo " <th>Status</th>" >> ./build_results.html + echo " <th>Nb Errors</th>" >> ./build_results.html + echo " <th>Nb Warnings</th>" >> ./build_results.html + echo " </tr>" >> ./build_results.html +} + +function summary_table_row { + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >$1</th>" >> ./build_results.html + if [ -f $2 ] + then + STATUS=`egrep -c "$3" $2` + if [ $STATUS -eq 1 ] + then + echo " <td bgcolor = \"green\" >OK</th>" >> ./build_results.html + else + echo " <td bgcolor = \"red\" >KO</th>" >> ./build_results.html + fi + NB_ERRORS=`egrep -c "error:" $2` + if [ $NB_ERRORS -eq 0 ] + then + echo " <td bgcolor = \"green\" >$NB_ERRORS</th>" >> ./build_results.html + else + echo " <td bgcolor = \"red\" >$NB_ERRORS</th>" >> ./build_results.html + fi + NB_WARNINGS=`egrep "warning:" $2 | egrep -v "jobserver unavailable|Clock skew detected.|flexran.proto" | egrep -c "warning:"` + if [ $NB_WARNINGS -eq 0 ] + then + echo " <td bgcolor = \"green\" >$NB_WARNINGS</th>" >> ./build_results.html + else + if [ $NB_WARNINGS -gt 20 ] + then + echo " <td bgcolor = \"red\" >$NB_WARNINGS</th>" >> ./build_results.html + else + echo " <td bgcolor = \"orange\" >$NB_WARNINGS</th>" >> ./build_results.html + fi + fi + if [ $NB_ERRORS -ne 0 ] || [ $NB_WARNINGS -ne 0 ] + then + details_table "$1" $2 $4 + fi + else + echo " <td bgcolor = \"lightgray\" >Unknown</th>" >> ./build_results.html + echo " <td bgcolor = \"lightgray\" >--</th>" >> ./build_results.html + echo " <td bgcolor = \"lightgray\" >--</th>" >> ./build_results.html + fi + echo " </tr>" >> ./build_results.html +} + +function summary_table_footer { + echo " </table>" >> ./build_results.html +} + +function sca_summary_table_header { + echo " <h3>$1</h3>" >> ./build_results.html + echo " <table border = \"1\">" >> ./build_results.html + echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html + echo " <th>Error / Warning Type</th>" >> ./build_results.html + echo " <th>Nb Errors</th>" >> ./build_results.html + echo " <th>Nb Warnings</th>" >> ./build_results.html + echo " </tr>" >> ./build_results.html + echo "0" > ccp_error_cnt.txt +} + +function sca_summary_table_row { + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >$2</td>" >> ./build_results.html + if [ -f $1 ] + then + NB_ERRORS=`egrep "severity=\"error\"" $1 | egrep -c "id=\"$3\""` + echo " <td>$NB_ERRORS</td>" >> ./build_results.html + echo " <td>N/A</td>" >> ./build_results.html + if [ -f ccp_error_cnt.txt ] + then + TOTAL_ERRORS=`cat ccp_error_cnt.txt` + TOTAL_ERRORS=$((TOTAL_ERRORS + NB_ERRORS)) + echo $TOTAL_ERRORS > ccp_error_cnt.txt + fi + else + echo " <td>Unknown</td>" >> ./build_results.html + echo " <td>Unknown</td>" >> ./build_results.html + fi + echo " </tr>" >> ./build_results.html +} + +function sca_summary_table_footer { + if [ -f $1 ] + then + NB_ERRORS=`egrep -c "severity=\"error\"" $1` + NB_WARNINGS=`egrep -c "severity=\"warning\"" $1` + if [ -f ccp_error_cnt.txt ] + then + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >Others</td>" >> ./build_results.html + TOTAL_ERRORS=`cat ccp_error_cnt.txt` + TOTAL_ERRORS=$((NB_ERRORS - TOTAL_ERRORS)) + echo " <td>$TOTAL_ERRORS</td>" >> ./build_results.html + echo " <td>$NB_WARNINGS</td>" >> ./build_results.html + echo " </tr>" >> ./build_results.html + rm -f ccp_error_cnt.txt + fi + echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html + echo " <th>Total</th>" >> ./build_results.html + echo " <th>$NB_ERRORS</th>" >> ./build_results.html + echo " <th>$NB_WARNINGS</th>" >> ./build_results.html + else + echo " <tr bgcolor = \"#33CCFF\" >" >> ./build_results.html + echo " <th>Total</th>" >> ./build_results.html + echo " <th>Unknown</th>" >> ./build_results.html + echo " <th>Unknown</th>" >> ./build_results.html + if [ -f ccp_error_cnt.txt ] + then + rm -f ccp_error_cnt.txt + fi + fi + echo " </tr>" >> ./build_results.html + echo " </table>" >> ./build_results.html + echo " <p>Full details in zipped artifact (cppcheck/cppcheck.xml) </p>" >> ./build_results.html + echo " <p>Graphical Interface tool : <code>cppcheck-gui -l cppcheck/cppcheck.xml</code> </p>" >> ./build_results.html +} + +jb_checker=0 +mr_checker=0 +pu_checker=0 +MR_TRIG=0 +PU_TRIG=0 +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + shift + usage + exit 0 + ;; + -gu|--git-url) + GIT_URL="$2" + let "jb_checker|=0x1" + shift + shift + ;; + -jn|--job-name) + JOB_NAME="$2" + let "jb_checker|=0x2" + shift + shift + ;; + -id|--build-id) + BUILD_ID="$2" + let "jb_checker|=0x4" + shift + shift + ;; + --trigger) + TRIG="$2" + case $TRIG in + merge-request) + MR_TRIG=1 + ;; + push) + PU_TRIG=1 + ;; + *) + echo "" + echo "Syntax Error: Invalid Trigger option -> $TRIG" + echo "" + trigger_usage + exit + ;; + esac + let "jb_checker|=0x8" + shift + shift + ;; + -mr) + MR_TRIG=1 + let "jb_checker|=0x8" + shift + ;; + -pu) + PU_TRIG=1 + let "jb_checker|=0x8" + shift + ;; + -sb|--src-branch) + SOURCE_BRANCH="$2" + let "mr_checker|=0x1" + shift + shift + ;; + -sc|--src-commit) + SOURCE_COMMIT_ID="$2" + let "mr_checker|=0x2" + shift + shift + ;; + -tb|--target-branch) + TARGET_BRANCH="$2" + let "mr_checker|=0x4" + shift + shift + ;; + -tc|--target-commit) + TARGET_COMMIT_ID="$2" + let "mr_checker|=0x8" + shift + shift + ;; + -br|--branch) + SOURCE_BRANCH="$2" + let "pu_checker|=0x1" + shift + shift + ;; + -co|--commit) + SOURCE_COMMIT_ID="$2" + let "pu_checker|=0x2" + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 + ;; +esac + +done + +if [ $jb_checker -ne 15 ] +then + echo "" + echo "Syntax Error: missing job information." + # TODO : list missing info + echo "" + exit 1 +fi + +if [ $PU_TRIG -eq 1 ] && [ $MR_TRIG -eq 1 ] +then + echo "" + echo "Syntax Error: trigger action incoherent." + echo "" + trigger_usage + exit 1 +fi + +if [ $PU_TRIG -eq 1 ] +then + if [ $pu_checker -ne 3 ] + then + echo "" + echo "Syntax Error: missing push information." + # TODO : list missing info + echo "" + exit 1 + fi +fi + +if [ $MR_TRIG -eq 1 ] +then + if [ $mr_checker -ne 15 ] + then + echo "" + echo "Syntax Error: missing merge-request information." + # TODO : list missing info + echo "" + exit 1 + fi +fi + +echo "<!DOCTYPE html>" > ./build_results.html +echo "<html class=\"no-js\" lang=\"en-US\">" >> ./build_results.html +echo "<head>" >> ./build_results.html +echo " <title>Build Results for $JOB_NAME job build #$BUILD_ID</title>" >> ./build_results.html +echo " <base href = \"http://www.openairinterface.org/\" />" >> ./build_results.html +echo "</head>" >> ./build_results.html +echo "<body>" >> ./build_results.html +echo " <table style=\"border-collapse: collapse; border: none;\">" >> ./build_results.html +echo " <tr style=\"border-collapse: collapse; border: none;\">" >> ./build_results.html +echo " <td style=\"border-collapse: collapse; border: none;\">" >> ./build_results.html +echo " <a href=\"http://www.openairinterface.org/\">" >> ./build_results.html +echo " <img src=\"/wp-content/uploads/2016/03/cropped-oai_final_logo2.png\" alt=\"\" border=\"none\" height=50 width=150>" >> ./build_results.html +echo " </img>" >> ./build_results.html +echo " </a>" >> ./build_results.html +echo " </td>" >> ./build_results.html +echo " <td style=\"border-collapse: collapse; border: none; vertical-align: center;\">" >> ./build_results.html +echo " <b><font size = \"6\">Job Summary -- Job: $JOB_NAME -- Build-ID: $BUILD_ID</font></b>" >> ./build_results.html +echo " </td>" >> ./build_results.html +echo " </tr>" >> ./build_results.html +echo " </table>" >> ./build_results.html +echo " <br>" >> ./build_results.html +echo " <table border = \"1\">" >> ./build_results.html +echo " <tr>" >> ./build_results.html +echo " <td bgcolor = \"lightcyan\" >GIT Repository</td>" >> ./build_results.html +echo " <td>$GIT_URL</td>" >> ./build_results.html +echo " </tr>" >> ./build_results.html +echo " <tr>" >> ./build_results.html +echo " <td bgcolor = \"lightcyan\" >Job Trigger</td>" >> ./build_results.html +if [ $PU_TRIG -eq 1 ]; then echo " <td>Push Event</td>" >> ./build_results.html; fi +if [ $MR_TRIG -eq 1 ]; then echo " <td>Merge-Request</td>" >> ./build_results.html; fi +echo " </tr>" >> ./build_results.html +if [ $PU_TRIG -eq 1 ] +then + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >Branch</td>" >> ./build_results.html + echo " <td>$SOURCE_BRANCH</td>" >> ./build_results.html + echo " </tr>" >> ./build_results.html + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >Commit ID</td>" >> ./build_results.html + echo " <td>$SOURCE_COMMIT_ID</td>" >> ./build_results.html + echo " </tr>" >> ./build_results.html +fi +if [ $MR_TRIG -eq 1 ] +then + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >Source Branch</td>" >> ./build_results.html + echo " <td>$SOURCE_BRANCH</td>" >> ./build_results.html + echo " </tr>" >> ./build_results.html + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >Source Commit ID</td>" >> ./build_results.html + echo " <td>$SOURCE_COMMIT_ID</td>" >> ./build_results.html + echo " </tr>" >> ./build_results.html + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >Target Branch</td>" >> ./build_results.html + echo " <td>$TARGET_BRANCH</td>" >> ./build_results.html + echo " </tr>" >> ./build_results.html + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >Target Commit ID</td>" >> ./build_results.html + echo " <td>$TARGET_COMMIT_ID</td>" >> ./build_results.html + echo " </tr>" >> ./build_results.html +fi +echo " </table>" >> ./build_results.html +echo " <h2>Build Summary</h2>" >> ./build_results.html + +if [ -f ./oai_rules_result.txt ] +then + echo " <h3>OAI Coding / Formatting Guidelines Check</h3>" >> ./build_results.html + echo " <table border = "1">" >> ./build_results.html + echo " <tr>" >> ./build_results.html + echo " <td bgcolor = \"lightcyan\" >Result:</td>" >> ./build_results.html + NB_FILES=`cat ./oai_rules_result.txt` + if [ $NB_FILES = "0" ] + then + if [ $PU_TRIG -eq 1 ]; then echo " <td bgcolor = \"green\">All files in repository follow OAI rules. </td>" >> ./build_results.html; fi + if [ $MR_TRIG -eq 1 ]; then echo " <td bgcolor = \"green\">All modified files in Merge-Request follow OAI rules.</td>" >> ./build_results.html; fi + else + if [ $PU_TRIG -eq 1 ]; then echo " <td bgcolor = \"orange\">$NB_FILES files in repository DO NOT follow OAI rules. </td>" >> ./build_results.html; fi + if [ $MR_TRIG -eq 1 ]; then echo " <td bgcolor = \"orange\">$NB_FILES modified files in Merge-Request DO NOT follow OAI rules.</td>" >> ./build_results.html; fi + fi + echo " </tr>" >> ./build_results.html + echo " </table>" >> ./build_results.html +fi + +sca_summary_table_header "OAI Static Code Analysis with CPPCHECK" +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Uninitialized variable" uninitvar +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Uninitialized struct member" uninitStructMember +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Memory leak" memleak +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Memory is freed twice" doubleFree +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Resource leak" resourceLeak +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Possible null pointer dereference" nullPointer +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Array access out of bounds" arrayIndexOutOfBounds +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Buffer is accessed out of bounds" bufferAccessOutOfBounds +sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Expression depends on order of evaluation of side effects" unknownEvaluationOrder +sca_summary_table_footer ./archives/cppcheck/cppcheck.xml + +summary_table_header "OAI Build eNB -- USRP option" +summary_table_row "LTE SoftModem - Release 14" ./archives/enb_usrp/lte-softmodem.Rel14.txt "Built target lte-softmodem" ./enb_usrp_row1.html +summary_table_row "Coding - Release 14" ./archives/enb_usrp/coding.Rel14.txt "Built target coding" ./enb_usrp_row2.html +summary_table_row "OAI USRP device if - Release 14" ./archives/enb_usrp/oai_usrpdevif.Rel14.txt "Built target oai_usrpdevif" ./enb_usrp_row3.html +summary_table_row "Parameters Lib Config - Release 14" ./archives/enb_usrp/params_libconfig.Rel14.txt "Built target params_libconfig" ./enb_usrp_row4.html +summary_table_footer + +if [ -f ./archives/basic_sim/basic_simulator_enb.txt ] +then + summary_table_header "OAI Build basic simulator option" + summary_table_row "Basic Simulator eNb - Release 14" ./archives/basic_sim/basic_simulator_enb.txt "Built target lte-softmodem" ./basic_sim_row1.html + summary_table_row "Basic Simulator UE - Release 14" ./archives/basic_sim/basic_simulator_ue.txt "Built target lte-uesoftmodem" ./basic_sim_row2.html + summary_table_row "Conf 2 UE data - Release 14" ./archives/basic_sim/conf2uedata.Rel14.txt "Built target conf2uedata" ./basic_sim_row3.html + summary_table_footer +fi + +summary_table_header "OAI Build Physical simulators option" +summary_table_row "DL Simulator - Release 14" ./archives/phy_sim/dlsim.Rel14.txt "Built target dlsim" ./phy_sim_row1.html +summary_table_row "UL Simulator - Release 14" ./archives/phy_sim/ulsim.Rel14.txt "Built target ulsim" ./phy_sim_row2.html +summary_table_row "Coding - Release 14" ./archives/phy_sim/coding.Rel14.txt "Built target coding" ./phy_sim_row3.html +summary_table_footer + +if [ -f archives/gnb_usrp/nr-softmodem.Rel14.txt ] +then + summary_table_header "OAI Build gNB -- USRP option" + summary_table_row "LTE SoftModem - Release 15" ./archives/gnb_usrp/nr-softmodem.Rel14.txt "Built target nr-softmodem" ./gnb_usrp_row1.html + summary_table_row "Coding - Release 14" ./archives/gnb_usrp/coding.Rel14.txt "Built target coding" ./gnb_usrp_row2.html + summary_table_row "OAI USRP device if - Release 14" ./archives/gnb_usrp/oai_usrpdevif.Rel14.txt "Built target oai_usrpdevif" ./gnb_usrp_row3.html + summary_table_row "Parameters Lib Config - Release 14" ./archives/gnb_usrp/params_libconfig.Rel14.txt "Built target params_libconfig" ./gnb_usrp_row4.html + summary_table_footer +fi + +if [ -f archives/nrue_usrp/nr-uesoftmodem.Rel14.txt ] +then + summary_table_header "OAI Build 5G NR UE -- USRP option" + summary_table_row "UE SoftModem - Release 15" ./archives/nrue_usrp/nr-uesoftmodem.Rel14.txt "Built target nr-uesoftmodem" ./nrue_usrp_row1.html + summary_table_row "Coding - Release 14" ./archives/nrue_usrp/coding.Rel14.txt "Built target coding" ./nrue_usrp_row2.html + summary_table_row "OAI USRP device if - Release 14" ./archives/nrue_usrp/oai_usrpdevif.Rel14.txt "Built target oai_usrpdevif" ./nrue_usrp_row3.html + summary_table_row "Parameters Lib Config - Release 14" ./archives/nrue_usrp/params_libconfig.Rel14.txt "Built target params_libconfig" ./nrue_usrp_row4.html + summary_table_footer +fi + +if [ -f archives/enb_eth/lte-softmodem-nos1.Rel14.txt ] +then + summary_table_header "OAI Build eNB -- ETHERNET transport option" + summary_table_row "LTE SoftModem w/o S1 - Release 14" ./archives/enb_eth/lte-softmodem-nos1.Rel14.txt "Built target lte-softmodem" ./enb_eth_row1.html + summary_table_row "Coding - Release 14" ./archives/enb_eth/coding.Rel14.txt "Built target coding" ./enb_eth_row2.html + summary_table_row "OAI ETHERNET transport - Release 14" ./archives/enb_eth/oai_eth_transpro.Rel14.txt "Built target oai_eth_transpro" ./enb_eth_row3.html + summary_table_row "Parameters Lib Config - Release 14" ./archives/enb_eth/params_libconfig.Rel14.txt "Built target params_libconfig" ./enb_eth_row4.html + summary_table_row "RB Tools - Release 14" ./archives/enb_eth/rb_tool.Rel14.txt "Built target rb_tool" ./enb_eth_row5.html + summary_table_row "NAS Mesh - Release 14" ./archives/enb_eth/nasmesh.Rel14.txt "Built target nasmesh" ./enb_eth_row6.html + summary_table_footer +fi + +if [ -f archives/ue_eth/lte-uesoftmodem-nos1.Rel14.txt ] +then + summary_table_header "OAI Build UE -- ETHERNET transport option" + summary_table_row "LTE UE SoftModem w/o S1 - Release 14" ./archives/ue_eth/lte-uesoftmodem-nos1.Rel14.txt "Built target lte-uesoftmodem" ./ue_eth_row1.html + summary_table_row "Coding - Release 14" ./archives/ue_eth/coding.Rel14.txt "Built target coding" ./ue_eth_row2.html + summary_table_row "OAI ETHERNET transport - Release 14" ./archives/ue_eth/oai_eth_transpro.Rel14.txt "Built target oai_eth_transpro" ./ue_eth_row3.html + summary_table_row "Parameters Lib Config - Release 14" ./archives/ue_eth/params_libconfig.Rel14.txt "Built target params_libconfig" ./ue_eth_row4.html + summary_table_row "RB Tools - Release 14" ./archives/ue_eth/rb_tool.Rel14.txt "Built target rb_tool" ./ue_eth_row5.html + summary_table_row "NAS Mesh - Release 14" ./archives/ue_eth/nasmesh.Rel14.txt "Built target nasmesh" ./ue_eth_row6.html + summary_table_footer +fi + +echo " <h3>Details</h3>" >> ./build_results.html + +for DETAILS_TABLE in `ls ./enb_usrp_row*.html` +do + cat $DETAILS_TABLE >> ./build_results.html +done +for DETAILS_TABLE in `ls ./basic_sim_row*.html` +do + cat $DETAILS_TABLE >> ./build_results.html +done +for DETAILS_TABLE in `ls ./phy_sim_row*.html` +do + cat $DETAILS_TABLE >> ./build_results.html +done +for DETAILS_TABLE in `ls ./gnb_usrp_row*.html` +do + cat $DETAILS_TABLE >> ./build_results.html +done +for DETAILS_TABLE in `ls ./nrue_usrp_row*.html` +do + cat $DETAILS_TABLE >> ./build_results.html +done +for DETAILS_TABLE in `ls ./enb_eth_row*.html` +do + cat $DETAILS_TABLE >> ./build_results.html +done +for DETAILS_TABLE in `ls ./ue_eth_row*.html` +do + cat $DETAILS_TABLE >> ./build_results.html +done +rm -f ./enb_usrp_row*.html ./basic_sim_row*.html ./phy_sim_row*.html ./gnb_usrp_row*.html ./nrue_usrp_row*.html ./enb_eth_row*.html ./ue_eth_row*.html + +echo "</body>" >> ./build_results.html +echo "</html>" >> ./build_results.html + +exit 0 diff --git a/ci-scripts/template-host.xml b/ci-scripts/template-host.xml new file mode 100644 index 0000000000000000000000000000000000000000..efd9912c7adf867cfa5678ab6623782fcb785233 --- /dev/null +++ b/ci-scripts/template-host.xml @@ -0,0 +1,27 @@ +<domain type='kvm'> + <os> + <type>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <cpu mode='host-passthrough'> + </cpu> + <devices> + <interface type='network'> + <source network='default'/> + <model type='virtio'/> + </interface> + <serial type='pty'> + <source path='/dev/pts/3'/> + <target port='0'/> + </serial> + <graphics type='vnc' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video/> + </devices> +</domain> diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 4df0cc51e17d48bf400a22596d8a75b151be9135..98587fb308024a294edb5d8cdb3e0233b04511e6 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1275,6 +1275,8 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/ ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c + ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_nr.c + ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_tools_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c @@ -1292,6 +1294,9 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/TOOLS/time_meas.c ${OPENAIR1_DIR}/PHY/TOOLS/lut.c ${OPENAIR1_DIR}/PHY/INIT/nr_init_ue.c + ${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c + #${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_common_ue.c + ${PHY_POLARSRC} ) @@ -1314,12 +1319,14 @@ add_library(PHY_RU ${PHY_SRC_RU}) #Layer 2 library ##################### set(MAC_DIR ${OPENAIR2_DIR}/LAYER2/MAC) +set(NR_UE_MAC_DIR ${OPENAIR2_DIR}/LAYER2/NR_MAC_UE) set(PHY_INTERFACE_DIR ${OPENAIR2_DIR}/PHY_INTERFACE) set(RLC_DIR ${OPENAIR2_DIR}/LAYER2/RLC) set(RLC_UM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0) set(RLC_AM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0) set(RLC_TM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0) set(RRC_DIR ${OPENAIR2_DIR}/RRC/LTE) +set(NR_UE_RRC_DIR ${OPENAIR2_DIR}/RRC/NR_UE) set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0) set(L2_SRC ${OPENAIR2_DIR}/LAYER2/openair2_proc.c @@ -1406,6 +1413,9 @@ set(L2_SRC_UE ${RRC_DIR}/rrc_common.c ${RRC_DIR}/L2_interface_common.c ${RRC_DIR}/L2_interface_ue.c + ${NR_UE_RRC_DIR}/L2_interface_ue.c + ${NR_UE_RRC_DIR}/main_ue.c + ${NR_UE_RRC_DIR}/rrc_UE.c ) set (MAC_SRC @@ -1437,6 +1447,10 @@ set (MAC_SRC_UE ${MAC_DIR}/l1_helpers.c ${MAC_DIR}/rar_tools_ue.c ${MAC_DIR}/config_ue.c + ${NR_UE_MAC_DIR}/config_ue.c + ${NR_UE_MAC_DIR}/mac_vars.c + ${NR_UE_MAC_DIR}/main_ue_nr.c + ${NR_UE_MAC_DIR}/nr_ue_procedures.c ) set (ENB_APP_SRC diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_ue_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..627c052df55651d49af81af9f3e886a5db4b882b --- /dev/null +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_ue_interface.h @@ -0,0 +1,565 @@ +/* + * Copyright 2017 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + + +#ifndef _NFAPI_NR_INTERFACE_NR_EXTENSION_H_ +#define _NFAPI_NR_INTERFACE_NR_EXTENSION_H_ +#define _NFAPI_NR_INTERFACE_H_ + +#include "stddef.h" + + + +#define NFAPI_NR_MAX_NUM_DL_ALLOCATIONS 16 +#define NFAPI_NR_MAX_NUM_UL_ALLOCATIONS 16 +#define NFAPI_NR_MAX_NUM_SERVING_CELLS 32 +#define NFAPI_NR_MAX_NUM_ZP_CSI_RS_RESOURCE_PER_SET 16 + +typedef unsigned int uint32_t; +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; +typedef signed int int32_t; +typedef signed short int16_t; +typedef signed char int8_t; + +typedef struct { + uint16_t phy_id; + uint16_t message_id; + uint16_t message_length; + uint16_t spare; +} nfapi_nr_p4_p5_message_header_t; + +typedef struct { + uint16_t phy_id; + uint16_t message_id; + uint16_t message_length; + uint16_t m_segment_sequence; /* This consists of 3 fields - namely, M, Segement & Sequence number*/ + uint32_t checksum; + uint32_t transmit_timestamp; +} nfapi_nr_p7_message_header_t; + +typedef struct { + uint16_t tag; + uint16_t length; +} nfapi_nr_tl_t; +#define NFAPI_NR_TAG_LENGTH_PACKED_LEN 4 + + + + + +typedef struct { + nfapi_nr_tl_t tl; + // common C-RNTI + uint8_t dci_format; + uint8_t frequency_domain_resouce_assignment; // 38.214 chapter 5.1.2.2 + uint8_t time_domain_resource_assignment; // 38.214 chapter 5.1.2.1 + uint8_t frequency_hopping_enabled_flag; + uint8_t frequency_hopping_bits; + uint8_t mcs; + uint8_t new_data_indication; + uint8_t redundancy_version; + uint8_t harq_process; + uint8_t tpc_command; + + uint8_t ul_sul_ind; + + uint8_t carrier_indicator; + uint8_t bwp_indndicator; + uint8_t vrb_to_prb_mapping; + uint8_t downlink_assignment_index_1; + uint8_t downlink_assignment_index_2; + uint8_t srs_resource_indicator; + uint8_t precoding_information; + uint8_t antenna_ports; + uint8_t srs_request; + uint8_t cqi_csi_request; + uint8_t cbg_transmission_information; + uint8_t ptrs_dmrs_association; + + uint8_t downlink_assignment_index; + uint8_t pucch_resource_indicator; + uint8_t pdsch_to_harq_feedback_timing_indicator; + + uint8_t short_messages_indicator; + + uint8_t prb_bundling_size_indicator; // 38.214 chapter 5.1.2.3 + uint8_t rate_matching_indicator; + uint8_t zp_csi_rs_trigger; + uint8_t transmission_configuration_indication; + uint8_t cbg_flushing_out_information; + + uint8_t slot_format_count; + uint8_t *slot_format_indicators; // 38.213 chapter 11.1.1 + + uint8_t preemption_indication_count; + uint8_t *preemption_indications; // 38.213 chapter 11.2 + + uint8_t tpc_command_count; + uint8_t *tpc_command_numbers; + + uint8_t block_number_count; + uint8_t *block_numbers; + uint8_t dci2_3_srs_request; // 38.212 table 7.3.1.1.2-5 + uint8_t dci2_3_tpc_command; + +} nfapi_nr_dci_pdu_rel15_t; +#define NFAPI_NR_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG 0x2020 + +typedef struct { + nfapi_nr_tl_t tl; + uint8_t uci_format; + uint8_t uci_channel; + uint8_t harq_ack_bits; + uint32_t harq_ack; + uint8_t csi_bits; + uint32_t csi; + uint8_t sr_bits; + uint32_t sr; +} nfapi_nr_uci_pdu_rel15_t; + + + + +// +// Top level NFAPI messages +// + + + +// +// P7 +// + + typedef struct { + uint16_t rnti; + uint8_t dci_type; + uint8_t dci_size; + nfapi_nr_dci_pdu_rel15_t dci; + }nfapi_nr_dci_indication_pdu_t; + + typedef struct { + nfapi_nr_tl_t tl; + uint16_t number_of_dcis; + nfapi_nr_dci_indication_pdu_t* dci_list; + } nfapi_nr_dci_indication_body_t; + +/// +typedef struct { + nfapi_nr_p7_message_header_t header; + uint16_t sfn_sf_slot; + nfapi_nr_dci_indication_body_t dci_indication_body; +} nfapi_nr_dci_indication_t; + + #define NFAPI_NR_TX_MAX_PDU 100 + typedef struct { + nfapi_nr_tl_t tl; + uint8_t* data; + } nfapi_nr_rx_request_body_t; + #define NFAPI_NR_TX_REQUEST_BODY_TAG 0x2022 + +/// +typedef struct { + nfapi_nr_p7_message_header_t header; + uint16_t sfn_sf_slot; + nfapi_nr_rx_request_body_t rx_request_body; +} nfapi_nr_rx_indication_t; + + typedef struct { + nfapi_nr_tl_t tl; + uint8_t ul_cqi; + uint16_t timing_advance; + } nfapi_nr_tx_indication_t; + + + #define NFAPI_NR_TX_MAX_SEGMENTS 32 + typedef struct { + uint16_t pdu_length; + uint16_t pdu_index; + uint8_t num_segments; + struct { + uint32_t segment_length; + uint8_t* segment_data; + } segments[NFAPI_NR_TX_MAX_SEGMENTS]; + + } nfapi_nr_tx_indication_pdu_t; + + #define NFAPI_NR_RX_IND_MAX_PDU 100 + typedef struct { + nfapi_nr_tl_t tl; + nfapi_nr_tx_indication_t tx_indication; + uint16_t number_of_pdus; + nfapi_nr_tx_indication_pdu_t* tx_pdu_list; + } nfapi_nr_tx_indication_body_t; + #define NFAPI_NR_RX_INDICATION_BODY_TAG 0x2023 + +/// +typedef struct { + nfapi_nr_p7_message_header_t header; + uint16_t sfn_sf_slot; + nfapi_nr_tx_indication_body_t tx_indication_body; +} nfapi_nr_tx_request_t; + + + typedef struct { + uint8_t pdu_type; + uint8_t pdu_size; + union { + /*nfapi_nr_ul_config_ulsch_pdu ulsch_pdu; + nfapi_nr_ul_config_ulsch_cqi_ri_pdu ulsch_cqi_ri_pdu; + nfapi_nr_ul_config_ulsch_harq_pdu ulsch_harq_pdu; + nfapi_nr_ul_config_ulsch_cqi_harq_ri_pdu ulsch_cqi_harq_ri_pdu; + nfapi_nr_ul_config_uci_cqi_pdu uci_cqi_pdu; + nfapi_nr_ul_config_uci_sr_pdu uci_sr_pdu; + nfapi_nr_ul_config_uci_harq_pdu uci_harq_pdu; + nfapi_nr_ul_config_uci_sr_harq_pdu uci_sr_harq_pdu; + nfapi_nr_ul_config_uci_cqi_harq_pdu uci_cqi_harq_pdu; + nfapi_nr_ul_config_uci_cqi_sr_pdu uci_cqi_sr_pdu; + nfapi_nr_ul_config_uci_cqi_sr_harq_pdu uci_cqi_sr_harq_pdu; + nfapi_nr_ul_config_srs_pdu srs_pdu; + nfapi_nr_ul_config_harq_buffer_pdu harq_buffer_pdu; + nfapi_nr_ul_config_ulsch_uci_csi_pdu ulsch_uci_csi_pdu; + nfapi_nr_ul_config_ulsch_uci_harq_pdu ulsch_uci_harq_pdu; + nfapi_nr_ul_config_ulsch_csi_uci_harq_pdu ulsch_csi_uci_harq_pdu;*/ + }; + } nfapi_nr_ul_config_request_pdu_t; + + typedef struct { + nfapi_nr_tl_t tl; + nfapi_nr_ul_config_request_pdu_t ul_config_pdu_list; + } nfapi_nr_ul_config_request_body_t; +/// +typedef struct { + nfapi_nr_p7_message_header_t header; + uint16_t sfn_sf_slot; + nfapi_nr_ul_config_request_body_t ul_config_request_body; +} nfapi_nr_ul_config_request_t; + + + + typedef struct { + uint8_t pdu_type; + uint8_t pdu_size; + union { + /*nfapi_nr_dl_config_dlsch_pdu dlsch_pdu; + nfapi_nr_dl_config_prs_pdu prs_pdu; + nfapi_nr_dl_config_csi_rs_pdu csi_rs_pdu;*/ + }; + } nfapi_nr_dl_config_request_pdu_t; + +/// +typedef struct { + nfapi_nr_p7_message_header_t header; + uint16_t sfn_sf_slot; + nfapi_nr_dl_config_request_pdu_t dl_config_request_body; +} nfapi_nr_dl_config_request_t; + + + +// +// P5 +// + + typedef struct { + uint32_t frequency_domain_resource; + uint8_t duration; + uint8_t cce_reg_mapping_type; // interleaved or noninterleaved + uint8_t cce_reg_interleaved_reg_bundle_size; // valid if CCE to REG mapping type is interleaved type + uint8_t cce_reg_interleaved_interleaver_size; // valid if CCE to REG mapping type is interleaved type + uint8_t cce_reg_interleaved_shift_index; // valid if CCE to REG mapping type is interleaved type + uint8_t precoder_granularity; + uint8_t tci_state_pdcch; + uint8_t tci_present_in_dci; + uint16_t pdcch_dmrs_scrambling_id; + } nfapi_nr_coreset_t; + + typedef struct { + nfapi_nr_coreset_t coreset; + + uint8_t monitoring_slot_peridicity; + uint8_t monitoring_slot_offset; + uint16_t duration; + uint16_t monitoring_symbols_within_slot; + uint8_t number_of_candidates[5]; // aggregation level 1, 2, 4, 8, 16 + + uint8_t dci_2_0_number_of_candidates[5]; // aggregation level 1, 2, 4, 8, 16 + uint8_t dci_2_3_monitorying_periodicity; + uint8_t dci_2_3_number_of_candidates; + + } nfapi_nr_search_space_t; + + typedef struct { + nfapi_nr_search_space_t search_space_sib1; + nfapi_nr_search_space_t search_space_others_sib; + nfapi_nr_search_space_t search_space_paging; + nfapi_nr_coreset_t coreset_ra; // common coreset + nfapi_nr_search_space_t search_space_ra; + } nfapi_nr_pdcch_config_common_t; + + typedef struct { + uint8_t k0; + uint8_t mapping_type; + uint8_t symbol_starting; + uint8_t symbol_length; + } nfapi_nr_pdsch_time_domain_resource_allocation_t; + + typedef struct { + nfapi_nr_pdsch_time_domain_resource_allocation_t allocation_list[NFAPI_NR_MAX_NUM_DL_ALLOCATIONS]; + } nfapi_nr_pdsch_config_common_t; + + typedef struct { + uint8_t prach_configuration_index; + uint8_t msg1_fdm; + uint8_t msg1_frequency_start; + uint8_t zero_correlation_zone_config; + uint8_t preamble_received_target_power; + uint8_t preamble_transmission_max; + uint8_t power_ramping_step; + uint8_t ra_window_size; + + uint8_t total_number_of_preamble; + uint8_t ssb_occasion_per_rach; + uint8_t cb_preamble_per_ssb; + + uint8_t group_a_msg3_size; + uint8_t group_a_number_of_preamble; + uint8_t group_b_power_offset; + uint8_t contention_resolution_timer; + uint8_t rsrp_threshold_ssb; + uint8_t rsrp_threshold_ssb_sul; + uint8_t prach_length; // l839, l139 + uint8_t prach_root_sequence_index; // 0 - 837 for l839, 0 - 137 for l139 + uint8_t msg1_subcarrier_spacing; + uint8_t restrictedset_config; + uint8_t msg3_transform_precoding; + } nfapi_nr_rach_config_common_t; + + typedef struct { + uint8_t k2; + uint8_t mapping_type; + uint8_t symbol_starting; + uint8_t symbol_length; + } nfapi_nr_pusch_time_domain_resource_allocation_t; + + typedef struct { + uint8_t group_hopping_enabled_transform_precoding; + nfapi_nr_pusch_time_domain_resource_allocation_t allocation_list[NFAPI_NR_MAX_NUM_UL_ALLOCATIONS]; + uint8_t msg3_delta_preamble; + uint8_t p0_nominal_with_grant; + } nfapi_nr_pusch_config_common_t; + + typedef struct { + uint8_t pucch_resource_common; + uint8_t pucch_group_hopping; + uint8_t hopping_id; + uint8_t p0_nominal; + } nfapi_nr_pucch_config_common_t; + + typedef struct { + uint8_t subcarrier_spacing_common; + uint8_t ssb_subcarrier_offset; + uint8_t dmrs_type_a_position; + uint8_t pdcch_config_sib1; + uint8_t cell_barred; + uint8_t intra_frquency_reselection; + } nfapi_nr_pbch_config_t; + + typedef struct { + nfapi_nr_tl_t tl; + + nfapi_nr_pdcch_config_common_t pdcch_config_common; + nfapi_nr_pdsch_config_common_t pdsch_config_common; + + } nfapi_nr_dl_bwp_common_config_t; + + + + typedef struct { + uint16_t int_rnti; + uint8_t time_frequency_set; + uint8_t dci_payload_size; + uint8_t serving_cell_id[NFAPI_NR_MAX_NUM_SERVING_CELLS]; // interrupt configuration per serving cell + uint8_t position_in_dci[NFAPI_NR_MAX_NUM_SERVING_CELLS]; // interrupt configuration per serving cell + } nfapi_nr_downlink_preemption_t; + + typedef struct { + uint8_t tpc_index; + uint8_t tpc_index_sul; + uint8_t target_cell; + } nfapi_nr_pusch_tpc_command_config_t; + + typedef struct { + uint8_t tpc_index_pcell; + uint8_t tpc_index_pucch_scell; + } nfapi_nr_pucch_tpc_command_config_t; + + typedef struct { + uint8_t starting_bit_of_format_2_3; + uint8_t feild_type_format_2_3; + } nfapi_nr_srs_tpc_command_config_t; + + typedef struct { + nfapi_nr_downlink_preemption_t downlink_preemption; + nfapi_nr_pusch_tpc_command_config_t tpc_pusch; + nfapi_nr_pucch_tpc_command_config_t tpc_pucch; + nfapi_nr_srs_tpc_command_config_t tpc_srs; + } nfapi_nr_pdcch_config_dedicated_t; + + typedef struct { + uint8_t dmrs_type; + uint8_t dmrs_addition_position; + uint8_t max_length; + uint16_t scrambling_id_0; + uint16_t scrambling_id_1; + uint8_t ptrs_frequency_density[2]; // phase tracking rs + uint8_t ptrs_time_density[3]; // phase tracking rs + uint8_t ptrs_epre_ratio; // phase tracking rs + uint8_t ptrs_resource_element_offset; // phase tracking rs + } nfapi_nr_dmrs_downlink_config_t; + + typedef struct { + uint8_t bwp_or_cell_level; + uint8_t pattern_type; + uint32_t resource_blocks[9]; // bitmaps type 275 bits + uint8_t slot_type; // bitmaps type one/two slot(s) + uint32_t symbols_in_resouece_block; // bitmaps type 14/28 bits + uint8_t periodic; // bitmaps type + uint32_t pattern[2]; // bitmaps type 2/4/5/8/10/20/40 bits + + nfapi_nr_coreset_t coreset; // coreset + + uint8_t subcarrier_spacing; + uint8_t mode; + } nfapi_nr_rate_matching_pattern_group_t; + + typedef struct { + // resource mapping + uint8_t row; // row1/row2/row4/other + uint16_t frequency_domain_allocation; // 4/12/3/6 bits + uint8_t number_of_ports; + uint8_t first_ofdm_symbol_in_time_domain; + uint8_t first_ofdm_symbol_in_time_domain2; + uint8_t cdm_type; + uint8_t density; // .5/1/3 + uint8_t density_dot5_type; // even/odd PRBs + + uint8_t frequency_band_starting_rb; // freqBand + uint8_t frequency_band_number_of_rb; // freqBand + + // periodicityAndOffset + uint8_t periodicity; // slot4/5/8/10/16/20/32/40/64/80/160/320/640 + uint32_t offset; // 0..639 bits + } nfapi_nr_zp_csi_rs_resource_t; + + typedef struct { + uint16_t data_scrambling_id_pdsch; + nfapi_nr_dmrs_downlink_config_t dmrs_dl_for_pdsch_mapping_type_a; + nfapi_nr_dmrs_downlink_config_t dmrs_dl_for_pdsch_mapping_type_b; + uint8_t vrb_to_prb_interleaver; + uint8_t resource_allocation; + nfapi_nr_pdsch_time_domain_resource_allocation_t allocation_list[NFAPI_NR_MAX_NUM_DL_ALLOCATIONS]; + uint8_t pdsch_aggregation_factor; + nfapi_nr_rate_matching_pattern_group_t rate_matching_pattern_group1; + nfapi_nr_rate_matching_pattern_group_t rate_matching_pattern_group2; + uint8_t rbg_size; + uint8_t mcs_table; + uint8_t max_num_of_code_word_scheduled_by_dci; + uint8_t bundle_size; // prb_bundling static + uint8_t bundle_size_set1; // prb_bundling dynamic + uint8_t bundle_size_set2; // prb_bundling dynamic + nfapi_nr_zp_csi_rs_resource_t periodically_zp_csi_rs_resource_set[NFAPI_NR_MAX_NUM_ZP_CSI_RS_RESOURCE_PER_SET]; + } nfapi_nr_pdsch_config_dedicated_t; + + typedef struct { + uint16_t starting_prb; + uint8_t intra_slot_frequency_hopping; + uint16_t second_hop_prb; + uint8_t format; // pucch format 0..4 + uint8_t initial_cyclic_shift; + uint8_t number_of_symbols; + uint8_t starting_symbol_index; + uint8_t time_domain_occ; + uint8_t number_of_prbs; + uint8_t occ_length; + uint8_t occ_index; + } nfapi_nr_pucch_resource_t; + + typedef struct { + uint8_t periodicity; + uint8_t number_of_harq_process; + nfapi_nr_pucch_resource_t n1_pucch_an; + } nfapi_nr_sps_config_t; + + typedef struct { + uint8_t beam_failure_instance_max_count; + uint8_t beam_failure_detection_timer; + } nfapi_nr_radio_link_monitoring_config_t; + + typedef struct { + nfapi_nr_pdcch_config_dedicated_t pdcch_config_dedicated; + nfapi_nr_pdsch_config_dedicated_t pdsch_config_dedicated; + nfapi_nr_sps_config_t sps_config; + nfapi_nr_radio_link_monitoring_config_t radio_link_monitoring_config; + + } nfapi_nr_dl_bwp_dedicated_config_t; + + typedef struct { + nfapi_nr_rach_config_common_t rach_config_common; + nfapi_nr_pusch_config_common_t pusch_config_common; + nfapi_nr_pucch_config_common_t pucch_config_common; + + } nfapi_nr_ul_bwp_common_config_t; + + typedef struct { + uint8_t inter_slot_frequency_hopping; + uint8_t additional_dmrs; + uint8_t max_code_rate; + uint8_t number_of_slots; + uint8_t pi2bpsk; + uint8_t simultaneous_harq_ack_csi; + } nfapi_nr_pucch_format_config_t; + + typedef struct { + nfapi_nr_pucch_format_config_t format1; + nfapi_nr_pucch_format_config_t format2; + nfapi_nr_pucch_format_config_t format3; + nfapi_nr_pucch_format_config_t format4; + nfapi_nr_pucch_resource_t multi_csi_pucch_resources[2]; + uint8_t dl_data_to_ul_ack[8]; + // pucch power control + uint8_t deltaF_pucch_f0; + uint8_t deltaF_pucch_f1; + uint8_t deltaF_pucch_f2; + uint8_t deltaF_pucch_f3; + uint8_t deltaF_pucch_f4; + uint8_t two_pucch_pc_adjusment_states; + } nfapi_nr_ul_bwp_dedicated_config_t; + +typedef struct { + nfapi_nr_p4_p5_message_header_t header; + uint8_t num_tlv; + + nfapi_nr_pbch_config_t pbch_config_common; // MIB + + nfapi_nr_dl_bwp_common_config_t dl_bwp_common; + nfapi_nr_dl_bwp_dedicated_config_t dl_bwp_dedicated; + + nfapi_nr_ul_bwp_common_config_t ul_bwp_common; + nfapi_nr_ul_bwp_dedicated_config_t ul_bwp_dedicated; + +} nfapi_nr_config_request_t; + +#endif /* _NFAPI_INTERFACE_H_ */ diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nr_fapi_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nr_fapi_ue_interface.h deleted file mode 100644 index fcfb7e7b25c5ea6971d0adeac1550a0a30e8d51b..0000000000000000000000000000000000000000 --- a/nfapi/open-nFAPI/nfapi/public_inc/nr_fapi_ue_interface.h +++ /dev/null @@ -1,3886 +0,0 @@ -/* - * Copyright 2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * 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. - */ - - -#ifndef _NFAPI_INTERFACE_NR_EXTENSION_H_ -#define _NFAPI_INTERFACE_NR_EXTENSION_H_ -#define _NFAPI_INTERFACE_H_ - -#include "stddef.h" - -// Constants - update based on implementation -#define NFAPI_MAX_PHY_RF_INSTANCES 2 -#define NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH 16 -#define NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH 3 -#define NFAPI_MAX_NUM_RF_BANDS 16 - -// The following definition control the size of arrays used in the interface. -// These may be changed if desired. They are used in the encoder to make sure -// that the user has not specified a 'count' larger than the max array, and also -// used by the decoder when decode an array. If the 'count' received is larger -// than the array it is to be stored in the decode fails. -#define NFAPI_MAX_NUM_ANTENNAS 8 -#define NFAPI_MAX_NUM_SUBBANDS 13 -#define NFAPI_MAX_BF_VECTORS 8 -#define NFAPI_MAX_CC 1 -#define NFAPI_MAX_NUM_PHYSICAL_ANTENNAS 8 -#define NFAPI_MAX_RSSI 8 -#define NFAPI_MAX_PSC_LIST 32 -#define NFAPI_MAX_PCI_LIST 32 -#define NFAPI_MAX_CARRIER_LIST 32 -#define NFAPI_MAX_ARFCN_LIST 128 -#define NFAPI_MAX_LTE_CELLS_FOUND 8 -#define NFAPI_MAX_UTRAN_CELLS_FOUND 8 -#define NFAPI_MAX_GSM_CELLS_FOUND 8 -#define NFAPI_MAX_NB_IOT_CELLS_FOUND 8 -#define NFAPI_MAX_SI_PERIODICITY 8 -#define NFAPI_MAX_SI_INDEX 8 -#define NFAPI_MAX_MIB_LENGTH 32 -#define NFAPI_MAX_SIB_LENGTH 256 -#define NFAPI_MAX_SI_LENGTH 256 -#define NFAPI_MAX_OPAQUE_DATA 64 -#define NFAPI_MAX_NUM_SCHEDULED_UES 8 // Used in the TPM structure -#define NFAPI_MAX_PNF_PHY 5 -#define NFAPI_MAX_PNF_PHY_RF_CONFIG 5 -#define NFAPI_MAX_PNF_RF 5 -#define NFAPI_MAX_NMM_FREQUENCY_BANDS 32 -#define NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS 100 -#define NFAPI_MAX_UL_DL_CONFIGURATIONS 5 -#define NFAPI_MAX_CSI_RS_RESOURCE_CONFIG 4 -#define NFAPI_MAX_ANTENNA_PORT_COUNT 8 -#define NFAPI_MAX_EPDCCH_PRB 8 -#define NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS 8 -#define NFAPI_MAX_NUMBER_ACK_NACK_TDD 8 -#define NFAPI_MAX_RO_DL 8 - -#define NFAPI_HEADER_LENGTH 8 -#define NFAPI_P7_HEADER_LENGTH 16 - -#define NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE 0xF000 -#define NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE 0xFFFF - -#define NFAPI_VERSION_3_0_11 0x000 -#define NFAPI_VERSION_3_0_12 0x001 - -// The IANA agreed port definition of the P5 SCTP VNF enpoint -// http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=7701 -#define NFAPI_P5_SCTP_PORT 7701 - -typedef unsigned int uint32_t; -typedef unsigned short uint16_t; -typedef unsigned char uint8_t; -typedef signed int int32_t; -typedef signed short int16_t; -typedef signed char int8_t; - -typedef struct { - uint16_t phy_id; - uint16_t message_id; - uint16_t message_length; - uint16_t spare; -} nfapi_p4_p5_message_header_t; - -typedef struct { - uint16_t phy_id; - uint16_t message_id; - uint16_t message_length; - uint16_t m_segment_sequence; /* This consists of 3 fields - namely, M, Segement & Sequence number*/ - uint32_t checksum; - uint32_t transmit_timestamp; -} nfapi_p7_message_header_t; - -#define NFAPI_PHY_ID_NA 0 - -//#define NFAPI_P7_GET_MORE(_mss) ( ((_mss) & 0x80) >> 7 ) -//#define NFAPI_P7_GET_SEGMENT(_mss) ( ((_mss) & 0x70) >> 4 ) -#define NFAPI_P7_GET_MORE(_mss) ( ((_mss) & 0x8000) >> 15 ) -#define NFAPI_P7_GET_SEGMENT(_mss) ( ((_mss) & 0x7F00) >> 8 ) -#define NFAPI_P7_GET_SEQUENCE(_mss) ( (_mss) & 0x00FF ) -#define NFAPI_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 7) | (((_segm) & 0x7) << 4) | ((_sequ) & 0xF) ) - -typedef struct { - uint16_t tag; - uint16_t length; -} nfapi_tl_t; -#define NFAPI_TAG_LENGTH_PACKED_LEN 4 - -// Convenience methods to convert between SFN/SFN formats -#define NFAPI_SFNSF2DEC(_sfnsf) ((((_sfnsf) >> 4) * 10) + ((_sfnsf) & 0xF)) -#define NFAPI_SFNSFDEC2SFNSF(_sfnsf_dec) ((((_sfnsf_dec) / 10) << 4) | (((_sfnsf_dec) - (((_sfnsf_dec) / 10) * 10)) & 0xF)) - -#define NFAPI_SFNSF2SFN(_sfnsf) ((_sfnsf) >> 4) -#define NFAPI_SFNSF2SF(_sfnsf) ((_sfnsf) & 0xF) - -#define NFAPI_MAX_SFNSFDEC 10240 - -typedef nfapi_tl_t* nfapi_vendor_extension_tlv_t; - - -// nFAPI Message IDs -typedef enum { - NFAPI_DL_CONFIG_REQUEST = 0x0080, - NFAPI_UL_CONFIG_REQUEST, - NFAPI_SUBFRAME_INDICATION, - NFAPI_HI_DCI0_REQUEST, - NFAPI_TX_REQUEST, - NFAPI_HARQ_INDICATION, - NFAPI_CRC_INDICATION, - NFAPI_RX_ULSCH_INDICATION, - NFAPI_RACH_INDICATION, - NFAPI_SRS_INDICATION, - NFAPI_RX_SR_INDICATION, - NFAPI_RX_CQI_INDICATION, - NFAPI_LBT_DL_CONFIG_REQUEST, - NFAPI_LBT_DL_INDICATION, - NFAPI_NB_HARQ_INDICATION, - NFAPI_NRACH_INDICATION, - - NFAPI_PNF_PARAM_REQUEST = 0x0100, - NFAPI_PNF_PARAM_RESPONSE, - NFAPI_PNF_CONFIG_REQUEST, - NFAPI_PNF_CONFIG_RESPONSE, - NFAPI_PNF_START_REQUEST, - NFAPI_PNF_START_RESPONSE, - NFAPI_PNF_STOP_REQUEST, - NFAPI_PNF_STOP_RESPONSE, - NFAPI_PARAM_REQUEST, - NFAPI_PARAM_RESPONSE, - NFAPI_CONFIG_REQUEST, - NFAPI_CONFIG_RESPONSE, - NFAPI_START_REQUEST, - NFAPI_START_RESPONSE, - NFAPI_STOP_REQUEST, - NFAPI_STOP_RESPONSE, - NFAPI_MEASUREMENT_REQUEST, - NFAPI_MEASUREMENT_RESPONSE, - - NFAPI_UL_NODE_SYNC = 0x0180, - NFAPI_DL_NODE_SYNC, - NFAPI_TIMING_INFO, - - - NFAPI_RSSI_REQUEST = 0x0200, - NFAPI_RSSI_RESPONSE, - NFAPI_RSSI_INDICATION, - NFAPI_CELL_SEARCH_REQUEST, - NFAPI_CELL_SEARCH_RESPONSE, - NFAPI_CELL_SEARCH_INDICATION, - NFAPI_BROADCAST_DETECT_REQUEST, - NFAPI_BROADCAST_DETECT_RESPONSE, - NFAPI_BROADCAST_DETECT_INDICATION, - NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST, - NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE, - NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION, - NFAPI_SYSTEM_INFORMATION_REQUEST, - NFAPI_SYSTEM_INFORMATION_RESPONSE, - NFAPI_SYSTEM_INFORMATION_INDICATION, - NFAPI_NMM_STOP_REQUEST, - NFAPI_NMM_STOP_RESPONSE, - - NFAPI_VENDOR_EXT_MSG_MIN = 0x0300, - NFAPI_VENDOR_EXT_MSG_MAX = 0x03FF, - - - NFAPI_MAX_MESSAGE_ID, -} nfapi_message_id_e; - -// nFAPI Error Codes -typedef enum { - NFAPI_MSG_OK = 0, - NFAPI_MSG_INVALID_STATE, - NFAPI_MSG_INVALID_CONFIG, - NFAPI_SFN_OUT_OF_SYNC, - NFAPI_MSG_SUBFRAME_ERR, - NFAPI_MSG_BCH_MISSING, - NFAPI_MSG_INVALID_SFN, - NFAPI_MSG_HI_ERR, - NFAPI_MSG_TX_ERR, - - NFAPI_LBT_NO_PDU_IN_DL_REQ, - NFAPI_LBT_NO_VALID_CONFIG_REQ_RECEIVED, - NFAPI_FAPI_E_LBT_SF_SFN_PASSED_END_SF_SFN, - NFAPI_FAPI_E_LBT_OVERLAP, - NFAPI_MSG_BCH_PRESENT, - - NFAPI_NBIOT_UNEXPECTED_REQ, - - // This is special return code that indicates that a response has - // been send via P9 - NFAPI_MSG_P9_RESPONSE = 0xAA -} nfapi_error_code_e; - - -typedef enum { - NFAPI_P4_MSG_OK = 100, - NFAPI_P4_MSG_INVALID_STATE = 101, - NFAPI_P4_MSG_INVALID_CONFIG = 102, - NFAPI_P4_MSG_RAT_NOT_SUPPORTED = 103, - NFAPI_P4_MSG_NMM_STOP_OK = 200, - NFAPI_P4_MSG_NMM_STOP_IGNOREDED = 201, - NFAPI_P4_MSG_NMM_STOP_INVALID_STATE = 202, - NFAPI_P4_MSG_PROCEDURE_COMPLETE = 300, - NFAPI_P4_MSG_PROCEDURE_STOPPED = 301, - NFAPI_P4_MSG_PARTIAL_RESULTS = 302, - NFAPI_P4_MSG_TIMEOUT = 303 -} nfapi_p4_error_code_e; - -// nFAPI enums -typedef enum { - NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE = 0, - NFAPI_DL_CONFIG_BCH_PDU_TYPE, - NFAPI_DL_CONFIG_MCH_PDU_TYPE, - NFAPI_DL_CONFIG_DLSCH_PDU_TYPE, - NFAPI_DL_CONFIG_PCH_PDU_TYPE, - NFAPI_DL_CONFIG_PRS_PDU_TYPE, - NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE, - NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE, - NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE, - NFAPI_DL_CONFIG_NBCH_PDU_TYPE, - NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE, - NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE -} nfapi_dl_config_pdu_type_e; - -typedef enum { - NFAPI_DL_DCI_FORMAT_1 = 0, - NFAPI_DL_DCI_FORMAT_1A, - NFAPI_DL_DCI_FORMAT_1B, - NFAPI_DL_DCI_FORMAT_1C, - NFAPI_DL_DCI_FORMAT_1D, - NFAPI_DL_DCI_FORMAT_2, - NFAPI_DL_DCI_FORMAT_2A, - NFAPI_DL_DCI_FORMAT_2B, - NFAPI_DL_DCI_FORMAT_2C -} nfapi_dl_dci_format_e; - -typedef enum { - NFAPI_UL_DCI_FORMAT_0 = 0, - NFAPI_UL_DCI_FORMAT_3, - NFAPI_UL_DCI_FORMAT_3A, - NFAPI_UL_DCI_FORMAT_4 -} nfapi_ul_dci_format_e; - -typedef enum { - NFAPI_UL_CONFIG_ULSCH_PDU_TYPE = 0, - NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE, - NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE, - NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE, - NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE, - NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE, - NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE, - NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE, - NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE, - NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE, - NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE, - NFAPI_UL_CONFIG_SRS_PDU_TYPE, - NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE, - NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE, - NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE, - NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE, - NFAPI_UL_CONFIG_NULSCH_PDU_TYPE, - NFAPI_UL_CONFIG_NRACH_PDU_TYPE, -} nfapi_ul_config_pdu_type_e; - -typedef enum { - NFAPI_HI_DCI0_HI_PDU_TYPE = 0, - NFAPI_HI_DCI0_DCI_PDU_TYPE, - NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE, - NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE, - NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE, -} nfapi_hi_dci0_pdu_type_e; - -typedef enum { - NFAPI_HARQ_ACK = 1, - NFAPI_HARQ_NACK, - NFAPI_HARQ_ACK_OR_NACK, - NFAPI_HARQ_DTX, - NFAPI_HARQ_ACK_OR_DTX, - NFAPI_HARQ_NACK_OR_DTX, - NFAPI_HARQ_ACK_OR_NACK_OR_DTX -} nfapi_harq_type_e; - -typedef enum { - NFAPI_CSI_REPORT_TYPE_PERIODIC = 0, - NFAPI_CSI_REPORT_TYPE_APERIODIC -} nfapi_csi_report_type_e; - -typedef enum { - NFAPI_DL_BW_SUPPORTED_6 = 1, - NFAPI_DL_BW_SUPPORTED_15 = 2, - NFAPI_DL_BW_SUPPORTED_25 = 4, - NFAPI_DL_BW_SUPPORTED_50 = 8, - NFAPI_DL_BW_SUPPORTED_75 = 16, - NFAPI_DL_BW_SUPPORTED_100 = 32 -} nfapi_dl_bandwith_supported_e; - -typedef enum { - NFAPI_UL_BW_SUPPORTED_6 = 1, - NFAPI_UL_BW_SUPPORTED_15 = 2, - NFAPI_UL_BW_SUPPORTED_25 = 4, - NFAPI_UL_BW_SUPPORTED_50 = 8, - NFAPI_UL_BW_SUPPORTED_75 = 16, - NFAPI_UL_BW_SUPPORTED_100 = 32 -} nfapi_ul_bandwith_supported_e; - -typedef enum { - NFAPI_3GPP_REL_SUPPORTED_8 = 0, - NFAPI_3GPP_REL_SUPPORTED_9 = 1, - NFAPI_3GPP_REL_SUPPORTED_10 = 2, - NFAPI_3GPP_REL_SUPPORTED_11 = 4, - NFAPI_3GPP_REL_SUPPORTED_12 = 8, - NFAPI_3GPP_REL_SUPPORTED_15 = 64 -} nfapi_3gpp_release_supported_e; - - -typedef enum { - NFAPI_DUPLEXING_MODE_TDD = 0, - NFAPI_DUPLEXING_MODE_FDD = 1, - NFAPI_DUPLEXING_MODE_HD_FDD = 2, -} nfapi_duplexing_mode_e; - -typedef enum { - NFAPI_CP_NORMAL = 0, - NFAPI_CP_EXTENDED = 1 -} nfapi_cyclic_prefix_type_e; - -typedef enum { - NFAPI_RAT_TYPE_LTE = 0, - NFAPI_RAT_TYPE_UTRAN = 1, - NFAPI_RAT_TYPE_GERAN = 2, - NFAPI_RAT_TYPE_NB_IOT = 3, - NFAPI_RAT_TYPE_NR = 4 -} nfapi_rat_type_e; - -typedef enum { - NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING, - NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING, - NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING, - NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION, - NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3, - NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4, - NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5 -} nfapi_harq_indication_tdd_ack_nackformat_e; - - -typedef enum { - NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE = 0, - NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE -} nfapi_lbt_dl_config_pdu_type_e; - -typedef enum { - NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE = 0, - NFAPI_LBT_DL_RSP_DRS_PDU_TYPE -} nfapi_lbt_dl_rsp_pdu_type_e; - -typedef struct { - nfapi_tl_t tl; - uint32_t length; - uint8_t value[NFAPI_MAX_OPAQUE_DATA]; -} nfapi_opaqaue_data_t; - -// Utility functions to turn enums into char* -const char* nfapi_error_code_to_str(nfapi_error_code_e value); - - -// P5 Sub Structures -typedef struct { - nfapi_tl_t tl; - uint8_t nfapi_sync_mode; - uint8_t location_mode; - uint16_t location_coordinates_length; - uint8_t location_coordinates[NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH]; - uint32_t dl_config_timing; - uint32_t tx_timing; - uint32_t ul_config_timing; - uint32_t hi_dci0_timing; - uint16_t maximum_number_phys; - uint16_t maximum_total_bandwidth; - uint8_t maximum_total_number_dl_layers; - uint8_t maximum_total_number_ul_layers; - uint8_t shared_bands; - uint8_t shared_pa; - int16_t maximum_total_power; - uint8_t oui[NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH]; -} nfapi_pnf_param_general_t; -#define NFAPI_PNF_PARAM_GENERAL_TAG 0x1000 - - - - - -typedef struct { - uint16_t rf_config_index; -} nfapi_rf_config_info_t; - -typedef struct { - uint16_t phy_config_index; - uint16_t number_of_rfs; - nfapi_rf_config_info_t rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG]; - uint16_t number_of_rf_exclusions; - nfapi_rf_config_info_t excluded_rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG]; - uint16_t downlink_channel_bandwidth_supported; - uint16_t uplink_channel_bandwidth_supported; - uint8_t number_of_dl_layers_supported; - uint8_t number_of_ul_layers_supported; - uint16_t maximum_3gpp_release_supported; - uint8_t nmm_modes_supported; -} nfapi_pnf_phy_info_t; - - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_phys; - nfapi_pnf_phy_info_t phy[NFAPI_MAX_PNF_PHY]; -} nfapi_pnf_phy_t; -#define NFAPI_PNF_PHY_TAG 0x1001 - -typedef struct { - uint16_t phy_config_index; - uint16_t transmission_mode_7_supported; - uint16_t transmission_mode_8_supported; - uint16_t two_antenna_ports_for_pucch; - uint16_t transmission_mode_9_supported; - uint16_t simultaneous_pucch_pusch; - uint16_t four_layer_tx_with_tm3_and_tm4; -} nfapi_pnf_phy_rel10_info_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_phys; - nfapi_pnf_phy_rel10_info_t phy[NFAPI_MAX_PNF_PHY]; -} nfapi_pnf_phy_rel10_t; -#define NFAPI_PNF_PHY_REL10_TAG 0x100A - -typedef struct { - uint16_t phy_config_index; - uint16_t edpcch_supported; - uint16_t multi_ack_csi_reporting; - uint16_t pucch_tx_diversity; - uint16_t ul_comp_supported; - uint16_t transmission_mode_5_supported; -} nfapi_pnf_phy_rel11_info_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_phys; - nfapi_pnf_phy_rel11_info_t phy[NFAPI_MAX_PNF_PHY]; -} nfapi_pnf_phy_rel11_t; -#define NFAPI_PNF_PHY_REL11_TAG 0x100B - - -typedef struct { - uint16_t phy_config_index; - uint16_t csi_subframe_set; - uint16_t enhanced_4tx_codebook; - uint16_t drs_supported; - uint16_t ul_64qam_supported; - uint16_t transmission_mode_10_supported; - uint16_t alternative_bts_indices; -} nfapi_pnf_phy_rel12_info_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_phys; - nfapi_pnf_phy_rel12_info_t phy[NFAPI_MAX_PNF_PHY]; -} nfapi_pnf_phy_rel12_t; -#define NFAPI_PNF_PHY_REL12_TAG 0x100C - -typedef struct { - uint16_t phy_config_index; - uint16_t pucch_format4_supported; - uint16_t pucch_format5_supported; - uint16_t more_than_5_ca_support; - uint16_t laa_supported; - uint16_t laa_ending_in_dwpts_supported; - uint16_t laa_starting_in_second_slot_supported; - uint16_t beamforming_supported; - uint16_t csi_rs_enhancement_supported; - uint16_t drms_enhancement_supported; - uint16_t srs_enhancement_supported; -} nfapi_pnf_phy_rel13_info_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_phys; - nfapi_pnf_phy_rel13_info_t phy[NFAPI_MAX_PNF_PHY]; -} nfapi_pnf_phy_rel13_t; -#define NFAPI_PNF_PHY_REL13_TAG 0x100D - -typedef struct { - uint16_t phy_config_index; - uint16_t number_of_rfs; - nfapi_rf_config_info_t rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG]; - uint16_t number_of_rf_exclusions; - nfapi_rf_config_info_t excluded_rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG]; - uint8_t number_of_dl_layers_supported; - uint8_t number_of_ul_layers_supported; - uint16_t maximum_3gpp_release_supported; - uint8_t nmm_modes_supported; -} nfapi_pnf_phy_rel13_nb_iot_info_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_phys; - nfapi_pnf_phy_rel13_nb_iot_info_t phy[NFAPI_MAX_PNF_PHY]; -} nfapi_pnf_phy_rel13_nb_iot_t; -#define NFAPI_PNF_PHY_REL13_NB_IOT_TAG 0x100E - -typedef struct { - uint16_t phy_config_index; -} nfapi_pnf_phy_rel15_info_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_phys; - nfapi_pnf_phy_rel15_info_t phy[NFAPI_MAX_PNF_PHY]; -} nfapi_pnf_phy_rel15_t; -#define NFAPI_PNF_PHY_REL15_TAG 0x100H - - -typedef struct { - uint16_t rf_config_index; - uint16_t band; - int16_t maximum_transmit_power; - int16_t minimum_transmit_power; - uint8_t number_of_antennas_suppported; - uint32_t minimum_downlink_frequency; - uint32_t maximum_downlink_frequency; - uint32_t minimum_uplink_frequency; - uint32_t maximum_uplink_frequency; -} nfapi_pnf_rf_info_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_rfs; - nfapi_pnf_rf_info_t rf[NFAPI_MAX_PNF_RF]; -} nfapi_pnf_rf_t; -#define NFAPI_PNF_RF_TAG 0x1002 - -typedef struct { - uint16_t phy_id; - uint16_t phy_config_index; - uint16_t rf_config_index; -} nfapi_phy_rf_config_info_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_phy_rf_config_info; - nfapi_phy_rf_config_info_t phy_rf_config[NFAPI_MAX_PHY_RF_INSTANCES]; -} nfapi_pnf_phy_rf_config_t; -#define NFAPI_PNF_PHY_RF_TAG 0x1003 - -// Generic strucutre for single tlv value. -typedef struct { - nfapi_tl_t tl; - uint16_t value; -} nfapi_uint16_tlv_t; - -typedef struct { - nfapi_tl_t tl; - int16_t value; -} nfapi_int16_tlv_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t value; -} nfapi_uint8_tlv_t; - -typedef struct { - nfapi_uint16_tlv_t phy_state; -} nfapi_l1_status; - -#define NFAPI_L1_STATUS_PHY_STATE_TAG 0x00FA - -typedef struct { - nfapi_uint16_tlv_t dl_bandwidth_support; - nfapi_uint16_tlv_t ul_bandwidth_support; - nfapi_uint16_tlv_t dl_modulation_support; - nfapi_uint16_tlv_t ul_modulation_support; - nfapi_uint16_tlv_t phy_antenna_capability; - nfapi_uint16_tlv_t release_capability; - nfapi_uint16_tlv_t mbsfn_capability; -} nfapi_phy_capabilities_t; - -#define NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG 0x00C8 -#define NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG 0x00C9 -#define NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG 0x00CA -#define NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG 0x00CB -#define NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG 0x00CC -#define NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG 0x00CD -#define NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG 0x00CE - - -typedef struct { - nfapi_uint16_tlv_t data_report_mode; - nfapi_uint16_tlv_t sfnsf; -} nfapi_l23_config_t; - - -#define NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG 0x00F0 -#define NFAPI_L23_CONFIG_SFNSF_TAG 0x00F1 - -typedef struct { - nfapi_uint16_tlv_t numerology_index_mu; - nfapi_uint16_tlv_t duplex_mode; - nfapi_uint16_tlv_t pcfich_power_offset; - nfapi_uint16_tlv_t pb; - nfapi_uint16_tlv_t dl_cyclic_prefix_type; - nfapi_uint16_tlv_t ul_cyclic_prefix_type; -} nfapi_subframe_config_t; - -#define NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG 0x0001 -#define NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG 0x0002 -#define NFAPI_SUBFRAME_CONFIG_PB_TAG 0x0003 -#define NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG 0x0004 -#define NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG 0x0005 -#define NFAPI_SUBFRAME_CONFIG_NUMEROLOGY_INDEX_MU_TAG 0x0006 - -typedef struct { - nfapi_uint16_tlv_t dl_channel_bandwidth; - nfapi_uint16_tlv_t ul_channel_bandwidth; - nfapi_uint16_tlv_t reference_signal_power; - nfapi_uint16_tlv_t tx_antenna_ports; - nfapi_uint16_tlv_t rx_antenna_ports; -} nfapi_rf_config_t; - -#define NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG 0x000A -#define NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG 0x000B -#define NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG 0x000C -#define NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG 0x000D -#define NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG 0x000E - -typedef struct { - nfapi_uint16_tlv_t phich_resource; - nfapi_uint16_tlv_t phich_duration; - nfapi_uint16_tlv_t phich_power_offset; -} nfapi_phich_config_t; - -#define NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG 0x0014 -#define NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG 0x0015 -#define NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG 0x0016 - -typedef enum { - NFAPI_HALF_FRAME_INDEX_FIRST_HALF = 0, - NFAPI_HALF_FRAME_INDEX_SECOND_HALF = 1 -} nfapi_half_frame_index_e; - -typedef struct { - nfapi_uint16_tlv_t primary_synchronization_signal_epre_eprers; - nfapi_uint16_tlv_t secondary_synchronization_signal_epre_eprers; - nfapi_uint16_tlv_t physical_cell_id; - nfapi_half_frame_index_e half_frame_index; - nfapi_uint16_tlv_t ssb_subcarrier_offset; - nfapi_uint16_tlv_t ssb_position_in_burst; - nfapi_uint16_tlv_t ssb_periodicity; - nfapi_uint16_tlv_t ss_pbch_block_power; -} nfapi_sch_config_t; - -#define NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG 0x001E -#define NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG 0x001F -#define NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG 0x0020 -#define NFAPI_SCH_CONFIG_HALF_FRAME_INDEX_TAG 0x0021 -#define NFAPI_SCH_CONFIG_SSB_SUBCARRIER_OFFSET_TAG 0x0022 -#define NFAPI_SCH_CONFIG_SSB_POSITION_IN_BURST 0x0023 -#define NFAPI_SCH_CONFIG_SSB_PERIODICITY 0x0024 -#define NFAPI_SCH_CONFIG_SS_PBCH_BLOCK_POWER 0x0025 - -typedef struct { - nfapi_uint16_tlv_t configuration_index; - nfapi_uint16_tlv_t root_sequence_index; - nfapi_uint16_tlv_t zero_correlation_zone_configuration; - nfapi_uint16_tlv_t high_speed_flag; - nfapi_uint16_tlv_t frequency_offset; -} nfapi_prach_config_t; - -#define NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG 0x0028 -#define NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG 0x0029 -#define NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG 0x002A -#define NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG 0x002B -#define NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG 0x002C - -typedef struct { - nfapi_uint16_tlv_t hopping_mode; - nfapi_uint16_tlv_t hopping_offset; - nfapi_uint16_tlv_t number_of_subbands; -} nfapi_pusch_config_t; - -#define NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG 0x0032 -#define NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG 0x0033 -#define NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG 0x0034 - -typedef struct { - nfapi_uint16_tlv_t delta_pucch_shift; - nfapi_uint16_tlv_t n_cqi_rb; - nfapi_uint16_tlv_t n_an_cs; - nfapi_uint16_tlv_t n1_pucch_an; -} nfapi_pucch_config_t; - -#define NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG 0x003C -#define NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG 0x003D -#define NFAPI_PUCCH_CONFIG_N_AN_CS_TAG 0x003E -#define NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG 0x003F - -typedef struct { - nfapi_uint16_tlv_t bandwidth_configuration; - nfapi_uint16_tlv_t max_up_pts; - nfapi_uint16_tlv_t srs_subframe_configuration; - nfapi_uint16_tlv_t srs_acknack_srs_simultaneous_transmission; -} nfapi_srs_config_t; - -#define NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG 0x0046 -#define NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG 0x0047 -#define NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG 0x0048 -#define NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG 0x0049 - -typedef struct { - nfapi_uint16_tlv_t uplink_rs_hopping; - nfapi_uint16_tlv_t group_assignment; - nfapi_uint16_tlv_t cyclic_shift_1_for_drms; -} nfapi_uplink_reference_signal_config_t; - -#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG 0x0050 -#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG 0x0051 -#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG 0x0052 - - -typedef struct { - nfapi_uint16_tlv_t ed_threshold_lbt_pdsch; - nfapi_uint16_tlv_t ed_threshold_lbt_drs; - nfapi_uint16_tlv_t pd_threshold; - nfapi_uint16_tlv_t multi_carrier_type; - nfapi_uint16_tlv_t multi_carrier_tx; - nfapi_uint16_tlv_t multi_carrier_freeze; - nfapi_uint16_tlv_t tx_antenna_ports_drs; - nfapi_uint16_tlv_t tx_power_drs; -} nfapi_laa_config_t; - -#define NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG 0x0064 -#define NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG 0x0065 -#define NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG 0x0066 -#define NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG 0x0067 -#define NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG 0x0068 -#define NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG 0x0069 -#define NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG 0x006A -#define NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG 0x006B - -typedef struct { - - nfapi_uint16_tlv_t pbch_repetitions_enable_r13; - nfapi_uint16_tlv_t prach_catm_root_sequence_index; - nfapi_uint16_tlv_t prach_catm_zero_correlation_zone_configuration; - nfapi_uint16_tlv_t prach_catm_high_speed_flag; - nfapi_uint16_tlv_t prach_ce_level_0_enable; - nfapi_uint16_tlv_t prach_ce_level_0_configuration_index; - nfapi_uint16_tlv_t prach_ce_level_0_frequency_offset; - nfapi_uint16_tlv_t prach_ce_level_0_number_of_repetitions_per_attempt; - nfapi_uint16_tlv_t prach_ce_level_0_starting_subframe_periodicity; - nfapi_uint16_tlv_t prach_ce_level_0_hopping_enable; - nfapi_uint16_tlv_t prach_ce_level_0_hopping_offset; - nfapi_uint16_tlv_t prach_ce_level_1_enable; - nfapi_uint16_tlv_t prach_ce_level_1_configuration_index; - nfapi_uint16_tlv_t prach_ce_level_1_frequency_offset; - nfapi_uint16_tlv_t prach_ce_level_1_number_of_repetitions_per_attempt; - nfapi_uint16_tlv_t prach_ce_level_1_starting_subframe_periodicity; - nfapi_uint16_tlv_t prach_ce_level_1_hopping_enable; - nfapi_uint16_tlv_t prach_ce_level_1_hopping_offset; - nfapi_uint16_tlv_t prach_ce_level_2_enable; - nfapi_uint16_tlv_t prach_ce_level_2_configuration_index; - nfapi_uint16_tlv_t prach_ce_level_2_frequency_offset; - nfapi_uint16_tlv_t prach_ce_level_2_number_of_repetitions_per_attempt; - nfapi_uint16_tlv_t prach_ce_level_2_starting_subframe_periodicity; - nfapi_uint16_tlv_t prach_ce_level_2_hopping_enable; - nfapi_uint16_tlv_t prach_ce_level_2_hopping_offset; - nfapi_uint16_tlv_t prach_ce_level_3_enable; - nfapi_uint16_tlv_t prach_ce_level_3_configuration_index; - nfapi_uint16_tlv_t prach_ce_level_3_frequency_offset; - nfapi_uint16_tlv_t prach_ce_level_3_number_of_repetitions_per_attempt; - nfapi_uint16_tlv_t prach_ce_level_3_starting_subframe_periodicity; - nfapi_uint16_tlv_t prach_ce_level_3_hopping_enable; - nfapi_uint16_tlv_t prach_ce_level_3_hopping_offset; - nfapi_uint16_tlv_t pucch_interval_ulhoppingconfigcommonmodea; - nfapi_uint16_tlv_t pucch_interval_ulhoppingconfigcommonmodeb; -} nfapi_emtc_config_t; - -#define NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG 0x0078 -#define NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG 0x0079 -#define NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG 0x007A -#define NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG 0x007B -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG 0x007C -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG 0x007D -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG 0x007E -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x007F -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG 0x0080 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG 0x0081 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG 0x0082 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG 0x0083 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG 0x0084 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG 0x0085 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x0086 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG 0x0087 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG 0x0088 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG 0x0089 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG 0x008A -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG 0x008B -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG 0x008C -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x008D -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG 0x008E -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG 0x008F -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG 0x0090 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG 0x0091 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG 0x0092 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG 0x0093 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x0094 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG 0x0095 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG 0x0096 -#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG 0x0097 -#define NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG 0x0098 -#define NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG 0x0099 - -typedef struct { - nfapi_uint16_tlv_t operating_mode; - nfapi_uint16_tlv_t anchor; - nfapi_uint16_tlv_t prb_index; - nfapi_uint16_tlv_t control_region_size; - nfapi_uint16_tlv_t assumed_crs_aps; - nfapi_uint16_tlv_t nprach_config_0_enabled; - nfapi_uint16_tlv_t nprach_config_0_sf_periodicity; - nfapi_uint16_tlv_t nprach_config_0_start_time; - nfapi_uint16_tlv_t nprach_config_0_subcarrier_offset; - nfapi_uint16_tlv_t nprach_config_0_number_of_subcarriers; - nfapi_uint16_tlv_t nprach_config_0_cp_length; - nfapi_uint16_tlv_t nprach_config_0_number_of_repetitions_per_attempt; - nfapi_uint16_tlv_t nprach_config_1_enabled; - nfapi_uint16_tlv_t nprach_config_1_sf_periodicity; - nfapi_uint16_tlv_t nprach_config_1_start_time; - nfapi_uint16_tlv_t nprach_config_1_subcarrier_offset; - nfapi_uint16_tlv_t nprach_config_1_number_of_subcarriers; - nfapi_uint16_tlv_t nprach_config_1_cp_length; - nfapi_uint16_tlv_t nprach_config_1_number_of_repetitions_per_attempt; - nfapi_uint16_tlv_t nprach_config_2_enabled; - nfapi_uint16_tlv_t nprach_config_2_sf_periodicity; - nfapi_uint16_tlv_t nprach_config_2_start_time; - nfapi_uint16_tlv_t nprach_config_2_subcarrier_offset; - nfapi_uint16_tlv_t nprach_config_2_number_of_subcarriers; - nfapi_uint16_tlv_t nprach_config_2_cp_length; - nfapi_uint16_tlv_t nprach_config_2_number_of_repetitions_per_attempt; - nfapi_uint16_tlv_t three_tone_base_sequence; - nfapi_uint16_tlv_t six_tone_base_sequence; - nfapi_uint16_tlv_t twelve_tone_base_sequence; - nfapi_uint16_tlv_t three_tone_cyclic_shift; - nfapi_uint16_tlv_t six_tone_cyclic_shift; - nfapi_uint16_tlv_t dl_gap_config_enable; - nfapi_uint16_tlv_t dl_gap_threshold; - nfapi_uint16_tlv_t dl_gap_periodicity; - nfapi_uint16_tlv_t dl_gap_duration_coefficient; -} nfapi_nb_iot_config_t; - -#define NFAPI_NB_IOT_CONFIG_OPERATING_MODE_TAG 0x00A5 -#define NFAPI_NB_IOT_CONFIG_ANCHOR_TAG 0x00A6 -#define NFAPI_NB_IOT_CONFIG_PRB_INDEX_TAG 0x00A7 -#define NFAPI_NB_IOT_CONFIG_CONTROL_REGION_SIZE_TAG 0x00A8 -#define NFAPI_NB_IOT_CONFIG_ASSUMED_CRS_APS_TAG 0x00A9 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_ENABLED_TAG 0x00AA -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_SF_PERIODICITY_TAG 0x00AB -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_START_TIME_TAG 0x00AC -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_SUBCARRIER_OFFSET_TAG 0x00AD -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_NUMBER_OF_SUBCARRIERS_TAG 0x00AE -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_CP_LENGTH_TAG 0x00AF -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00B0 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_ENABLED_TAG 0x00B1 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_SF_PERIODICITY_TAG 0x00B2 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_START_TIME_TAG 0x00B3 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_SUBCARRIER_OFFSET_TAG 0x00B4 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_NUMBER_OF_SUBCARRIERS_TAG 0x00B5 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_CP_LENGTH_TAG 0x00B6 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00B7 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_ENABLED_TAG 0x00B8 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_SF_PERIODICITY_TAG 0x00B9 -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_START_TIME_TAG 0x00BA -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_SUBCARRIER_OFFSET_TAG 0x00BB -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_NUMBER_OF_SUBCARRIERS_TAG 0x00BC -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_CP_LENGTH_TAG 0x00BD -#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00BE -#define NFAPI_NB_IOT_CONFIG_THREE_TONE_BASE_SEQUENCE_TAG 0x00BF -#define NFAPI_NB_IOT_CONFIG_SIX_TONE_BASE_SEQUENCE_TAG 0x00C0 -#define NFAPI_NB_IOT_CONFIG_TWELVE_TONE_BASE_SEQUENCE_TAG 0x00C1 -#define NFAPI_NB_IOT_CONFIG_THREE_TONE_CYCLIC_SHIFT_TAG 0x00C2 -#define NFAPI_NB_IOT_CONFIG_SIX_TONE_CYCLIC_SHIFT_TAG 0x00C3 -#define NFAPI_NB_IOT_CONFIG_DL_GAP_CONFIG_ENABLE_TAG 0x00C4 -#define NFAPI_NB_IOT_CONFIG_DL_GAP_THRESHOLD_TAG 0x00C5 -#define NFAPI_NB_IOT_CONFIG_DL_GAP_PERIODICITY_TAG 0x00C6 -#define NFAPI_NB_IOT_CONFIG_DL_GAP_DURATION_COEFFICIENT_TAG 0x00C7 - -typedef struct { - nfapi_uint16_tlv_t laa_support; - nfapi_uint16_tlv_t pd_sensing_lbt_support; - nfapi_uint16_tlv_t multi_carrier_lbt_support; - nfapi_uint16_tlv_t partial_sf_support; -} nfapi_laa_capability_t; - -#define NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG 0x00D1 -#define NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG 0x00D2 -#define NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG 0x00D3 -#define NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG 0x00D4 - -typedef struct { - nfapi_uint16_tlv_t nb_iot_support; - nfapi_uint16_tlv_t nb_iot_operating_mode_capability; -} nfapi_nb_iot_capability_t; - -#define NFAPI_LAA_CAPABILITY_NB_IOT_SUPPORT_TAG 0x00D5 -#define NFAPI_LAA_CAPABILITY_NB_IOT_OPERATING_MODE_CAPABILITY_TAG 0x00D6 - -typedef struct { - nfapi_uint16_tlv_t subframe_assignment; - nfapi_uint16_tlv_t special_subframe_patterns; -} nfapi_tdd_frame_structure_t; - -#define NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG 0x005A -#define NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG 0x005B - -typedef struct { - nfapi_tl_t tl; - uint16_t number_rf_bands; - uint16_t rf_band[NFAPI_MAX_NUM_RF_BANDS]; -} nfapi_rf_bands_t; -#define NFAPI_PHY_RF_BANDS_TAG 0x0114 - -#define NFAPI_IPV4_ADDRESS_LENGTH 4 -#define NFAPI_IPV6_ADDRESS_LENGTH 16 - -// Convience enum to allow the ip addres type to be distinguished -typedef enum { - NFAPI_IP_ADDRESS_IPV4 = 0, - NFAPI_IP_ADDRESS_IPV6 -} nfapi_ip_address_type_e; - -// The type could be infered from the length, but it is clearer in -// code to have a type variable set -typedef struct { - nfapi_tl_t tl; - uint8_t type; - union { - uint8_t ipv4_address[NFAPI_IPV4_ADDRESS_LENGTH]; - uint8_t ipv6_address[NFAPI_IPV6_ADDRESS_LENGTH]; - } u; -} nfapi_ip_address_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t address[NFAPI_IPV4_ADDRESS_LENGTH]; -} nfapi_ipv4_address_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t address[NFAPI_IPV6_ADDRESS_LENGTH]; -} nfapi_ipv6_address_t; - - - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_rf_bands; - uint16_t bands[NFAPI_MAX_NMM_FREQUENCY_BANDS]; -} nfapi_nmm_frequency_bands_t; - -//These TLVs are used exclusively by nFAPI -typedef struct -{ - // These TLVs are used to setup the transport connection between VNF and PNF - nfapi_ipv4_address_t p7_vnf_address_ipv4; - nfapi_ipv6_address_t p7_vnf_address_ipv6; - nfapi_uint16_tlv_t p7_vnf_port; - - nfapi_ipv4_address_t p7_pnf_address_ipv4; - nfapi_ipv6_address_t p7_pnf_address_ipv6; - nfapi_uint16_tlv_t p7_pnf_port; - - // These TLVs are used to setup the transport connection between VNF and PNF - nfapi_uint8_tlv_t dl_ue_per_sf; - nfapi_uint8_tlv_t ul_ue_per_sf; - - // These TLVs are used by PNF to report its RF capabilities to the VNF software - nfapi_rf_bands_t rf_bands; - - // These TLVs are used by the VNF to configure the synchronization with the PNF. - nfapi_uint8_tlv_t timing_window; - nfapi_uint8_tlv_t timing_info_mode; - nfapi_uint8_tlv_t timing_info_period; - - // These TLVs are used by the VNF to configure the RF in the PNF - nfapi_uint16_tlv_t max_transmit_power; - nfapi_uint16_tlv_t earfcn; - - nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands; - nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands; - nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands; - nfapi_uint8_tlv_t nmm_uplink_rssi_supported; - -} nfapi_nfapi_t; - -#define NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x0100 -#define NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x0101 -#define NFAPI_NFAPI_P7_VNF_PORT_TAG 0x0102 -#define NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x0103 -#define NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x0104 -#define NFAPI_NFAPI_P7_PNF_PORT_TAG 0x0105 - -#define NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG 0x010A -#define NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG 0x010B -#define NFAPI_NFAPI_RF_BANDS_TAG 0x0114 -#define NFAPI_NFAPI_TIMING_WINDOW_TAG 0x011E -#define NFAPI_NFAPI_TIMING_INFO_MODE_TAG 0x011F -#define NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120 -#define NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG 0x0128 -#define NFAPI_NFAPI_EARFCN_TAG 0x0129 -#define NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG 0x0130 -#define NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG 0x0131 -#define NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG 0x0132 -#define NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG 0x0133 - - -// P5 Message Structures -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_pnf_param_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_pnf_param_general_t pnf_param_general; - nfapi_pnf_phy_t pnf_phy; - nfapi_pnf_rf_t pnf_rf; - nfapi_pnf_phy_rel10_t pnf_phy_rel10; - nfapi_pnf_phy_rel11_t pnf_phy_rel11; - nfapi_pnf_phy_rel12_t pnf_phy_rel12; - nfapi_pnf_phy_rel13_t pnf_phy_rel13; - nfapi_pnf_phy_rel13_nb_iot_t pnf_phy_rel13_nb_iot; - nfapi_pnf_phy_rel15_t pnf_phy_rel15; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_pnf_param_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_pnf_phy_rf_config_t pnf_phy_rf_config; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_pnf_config_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_pnf_config_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_pnf_start_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_pnf_start_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_pnf_stop_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_pnf_stop_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_param_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint8_t error_code; - uint8_t num_tlv; - // fdd or tdd in idle or configured tlvs - nfapi_l1_status l1_status; - nfapi_phy_capabilities_t phy_capabilities; - nfapi_laa_capability_t laa_capability; - nfapi_nb_iot_capability_t nb_iot_capability; - - nfapi_subframe_config_t subframe_config; - nfapi_rf_config_t rf_config; - nfapi_phich_config_t phich_config; - nfapi_sch_config_t sch_config; - nfapi_prach_config_t prach_config; - nfapi_pusch_config_t pusch_config; - nfapi_pucch_config_t pucch_config; - nfapi_srs_config_t srs_config; - nfapi_uplink_reference_signal_config_t uplink_reference_signal_config; - nfapi_tdd_frame_structure_t tdd_frame_structure_config; - nfapi_l23_config_t l23_config; - nfapi_nb_iot_config_t nb_iot_config; - - // addition nfapi tlvs as per table 2-16 in idle or configure - nfapi_nfapi_t nfapi_config; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_param_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint8_t num_tlv; - nfapi_subframe_config_t subframe_config; - nfapi_rf_config_t rf_config; - nfapi_phich_config_t phich_config; - nfapi_sch_config_t sch_config; - nfapi_prach_config_t prach_config; - nfapi_pusch_config_t pusch_config; - nfapi_pucch_config_t pucch_config; - nfapi_srs_config_t srs_config; - nfapi_uplink_reference_signal_config_t uplink_reference_signal_config; - nfapi_laa_config_t laa_config; - nfapi_emtc_config_t emtc_config; - nfapi_tdd_frame_structure_t tdd_frame_structure_config; - nfapi_l23_config_t l23_config; - nfapi_nb_iot_config_t nb_iot_config; - - // addition nfapi tlvs as per table 2-16 in idle or configure - nfapi_nfapi_t nfapi_config; - - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_config_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_config_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_start_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_start_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_stop_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_stop_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_uint16_tlv_t dl_rs_tx_power; - nfapi_uint16_tlv_t received_interference_power; - nfapi_uint16_tlv_t thermal_noise_power; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_measurement_request_t; - -#define NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG 0x1004 -#define NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG 0x1005 -#define NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG 0x1006 - - - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_resource_blocks; - int16_t received_interference_power[NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS]; -} nfapi_received_interference_power_measurement_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_int16_tlv_t dl_rs_tx_power_measurement; - nfapi_received_interference_power_measurement_t received_interference_power_measurement; - nfapi_int16_tlv_t thermal_noise_power_measurement; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_measurement_response_t; - -#define NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG 0x1007 -#define NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG 0x1008 -#define NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG 0x1009 - -// P7 Sub Structures -typedef struct { - nfapi_tl_t tl; - uint8_t dci_format; - uint8_t cce_idx; - uint8_t aggregation_level; - uint16_t rnti; - uint8_t resource_allocation_type; - uint8_t virtual_resource_block_assignment_flag; - uint32_t resource_block_coding; - uint8_t mcs_1; - uint8_t redundancy_version_1; - uint8_t new_data_indicator_1; - uint8_t transport_block_to_codeword_swap_flag; - uint8_t mcs_2; - uint8_t redundancy_version_2; - uint8_t new_data_indicator_2; - uint8_t harq_process; - uint8_t tpmi; - uint8_t pmi; - uint8_t precoding_information; - uint8_t tpc; - uint8_t downlink_assignment_index; - uint8_t ngap; - uint8_t transport_block_size_index; - uint8_t downlink_power_offset; - uint8_t allocate_prach_flag; - uint8_t preamble_index; - uint8_t prach_mask_index; - uint8_t rnti_type; - uint16_t transmission_power; -} nfapi_dl_config_dci_dl_pdu_rel8_t; -#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG 0x2001 - -typedef struct { - nfapi_tl_t tl; - uint8_t mcch_flag; - uint8_t mcch_change_notification; - uint8_t scrambling_identity; -} nfapi_dl_config_dci_dl_pdu_rel9_t; -#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG 0x2002 - -typedef struct { - nfapi_tl_t tl; - uint8_t cross_carrier_scheduling_flag; - uint8_t carrier_indicator; - uint8_t srs_flag; - uint8_t srs_request; - uint8_t antenna_ports_scrambling_and_layers; - uint8_t total_dci_length_including_padding; - uint8_t n_dl_rb; -} nfapi_dl_config_dci_dl_pdu_rel10_t; -#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG 0x2003 - - -typedef struct { - nfapi_tl_t tl; - uint8_t harq_ack_resource_offset; - uint8_t pdsch_re_mapping_quasi_co_location_indicator; -} nfapi_dl_config_dci_dl_pdu_rel11_t; - -#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG 0x2039 - - - -typedef struct { - nfapi_tl_t tl; - uint8_t primary_cell_type; - uint8_t ul_dl_configuration_flag; - uint8_t number_ul_dl_configurations; - uint8_t ul_dl_configuration_indication[NFAPI_MAX_UL_DL_CONFIGURATIONS]; -} nfapi_dl_config_dci_dl_pdu_rel12_t; - -#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG 0x203a - - - -typedef struct { - uint8_t subband_index; - uint8_t scheduled_ues; - uint16_t precoding_value[NFAPI_MAX_NUM_PHYSICAL_ANTENNAS][NFAPI_MAX_NUM_SCHEDULED_UES]; -} nfapi_dl_config_dci_dl_tpm_subband_info_t; - -typedef struct { - uint8_t num_prb_per_subband; - uint8_t number_of_subbands; - uint8_t num_antennas; - nfapi_dl_config_dci_dl_tpm_subband_info_t subband_info[NFAPI_MAX_NUM_SUBBANDS]; -} nfapi_dl_config_dci_dl_tpm_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t laa_end_partial_sf_flag; - uint8_t laa_end_partial_sf_configuration; - uint8_t initial_lbt_sf; - uint8_t codebook_size_determination; - uint8_t drms_table_flag; - uint8_t tpm_struct_flag; - nfapi_dl_config_dci_dl_tpm_t tpm; -} nfapi_dl_config_dci_dl_pdu_rel13_t; - -#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG 0x203b - -typedef struct { - nfapi_dl_config_dci_dl_pdu_rel8_t dci_dl_pdu_rel8; - nfapi_dl_config_dci_dl_pdu_rel9_t dci_dl_pdu_rel9; - nfapi_dl_config_dci_dl_pdu_rel10_t dci_dl_pdu_rel10; - nfapi_dl_config_dci_dl_pdu_rel11_t dci_dl_pdu_rel11; - nfapi_dl_config_dci_dl_pdu_rel12_t dci_dl_pdu_rel12; - nfapi_dl_config_dci_dl_pdu_rel13_t dci_dl_pdu_rel13; -} nfapi_dl_config_dci_dl_pdu; - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t pdu_index; - uint16_t transmission_power; -} nfapi_dl_config_bch_pdu_rel8_t; -#define NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG 0x2004 - -typedef struct { - nfapi_dl_config_bch_pdu_rel8_t bch_pdu_rel8; -} nfapi_dl_config_bch_pdu; - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t pdu_index; - uint16_t rnti; - uint8_t resource_allocation_type; - uint32_t resource_block_coding; - uint8_t modulation; - uint16_t transmission_power; - uint16_t mbsfn_area_id; -} nfapi_dl_config_mch_pdu_rel8_t; -#define NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG 0x2005 - -typedef struct { - nfapi_dl_config_mch_pdu_rel8_t mch_pdu_rel8; -} nfapi_dl_config_mch_pdu; - - -typedef struct { - uint8_t subband_index; - uint8_t num_antennas; - uint16_t bf_value[NFAPI_MAX_NUM_ANTENNAS]; -} nfapi_bf_vector_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t pdu_index; - uint16_t rnti; - uint8_t resource_allocation_type; - uint8_t virtual_resource_block_assignment_flag; - uint32_t resource_block_coding; - uint8_t modulation; - uint8_t redundancy_version; - uint8_t transport_blocks; - uint8_t transport_block_to_codeword_swap_flag; - uint8_t transmission_scheme; - uint8_t number_of_layers; - uint8_t number_of_subbands; - uint8_t codebook_index[NFAPI_MAX_NUM_SUBBANDS]; - uint8_t ue_category_capacity; - uint8_t pa; - uint8_t delta_power_offset_index; - uint8_t ngap; - uint8_t nprb; - uint8_t transmission_mode; - uint8_t num_bf_prb_per_subband; - uint8_t num_bf_vector; - nfapi_bf_vector_t bf_vector[NFAPI_MAX_BF_VECTORS]; -} nfapi_dl_config_dlsch_pdu_rel8_t; -#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG 0x2006 - -typedef struct { - nfapi_tl_t tl; - uint8_t nscid; -} nfapi_dl_config_dlsch_pdu_rel9_t; -#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG 0x2007 - -typedef struct { - nfapi_tl_t tl; - uint8_t csi_rs_flag; - uint8_t csi_rs_resource_config_r10; - uint16_t csi_rs_zero_tx_power_resource_config_bitmap_r10; - uint8_t csi_rs_number_nzp_configuration; - uint8_t csi_rs_resource_config[NFAPI_MAX_CSI_RS_RESOURCE_CONFIG]; - uint8_t pdsch_start; -} nfapi_dl_config_dlsch_pdu_rel10_t; -#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG 0x2008 - -typedef struct { - nfapi_tl_t tl; - uint8_t drms_config_flag; - uint16_t drms_scrambling; - uint8_t csi_config_flag; - uint16_t csi_scrambling; - uint8_t pdsch_re_mapping_flag; - uint8_t pdsch_re_mapping_atenna_ports; - uint8_t pdsch_re_mapping_freq_shift; -} nfapi_dl_config_dlsch_pdu_rel11_t; -#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG 0x203C - -typedef struct { - nfapi_tl_t tl; - uint8_t altcqi_table_r12; - uint8_t maxlayers; - uint8_t n_dl_harq; -} nfapi_dl_config_dlsch_pdu_rel12_t; -#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG 0x203D - -typedef struct { - nfapi_tl_t tl; - uint8_t dwpts_symbols; - uint8_t initial_lbt_sf; - uint8_t ue_type; - uint8_t pdsch_payload_type; - uint16_t initial_transmission_sf_io; - uint8_t drms_table_flag; -} nfapi_dl_config_dlsch_pdu_rel13_t; -#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG 0x203E - -typedef struct { - nfapi_dl_config_dlsch_pdu_rel8_t dlsch_pdu_rel8; - nfapi_dl_config_dlsch_pdu_rel9_t dlsch_pdu_rel9; - nfapi_dl_config_dlsch_pdu_rel10_t dlsch_pdu_rel10; - nfapi_dl_config_dlsch_pdu_rel11_t dlsch_pdu_rel11; - nfapi_dl_config_dlsch_pdu_rel12_t dlsch_pdu_rel12; - nfapi_dl_config_dlsch_pdu_rel13_t dlsch_pdu_rel13; -} nfapi_dl_config_dlsch_pdu; - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t pdu_index; - uint16_t p_rnti; - uint8_t resource_allocation_type; - uint8_t virtual_resource_block_assignment_flag; - uint32_t resource_block_coding; - uint8_t mcs; - uint8_t redundancy_version; - uint8_t number_of_transport_blocks; - uint8_t transport_block_to_codeword_swap_flag; - uint8_t transmission_scheme; - uint8_t number_of_layers; - uint8_t codebook_index; - uint8_t ue_category_capacity; - uint8_t pa; - uint16_t transmission_power; - uint8_t nprb; - uint8_t ngap; -} nfapi_dl_config_pch_pdu_rel8_t; -#define NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG 0x2009 - -typedef struct { - nfapi_tl_t tl; - uint8_t ue_mode; - uint16_t initial_transmission_sf_io; -} nfapi_dl_config_pch_pdu_rel13_t; -#define NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG 0x203F - -typedef struct { - nfapi_dl_config_pch_pdu_rel8_t pch_pdu_rel8; - nfapi_dl_config_pch_pdu_rel13_t pch_pdu_rel13; -} nfapi_dl_config_pch_pdu; - -typedef struct { - nfapi_tl_t tl; - uint16_t transmission_power; - uint8_t prs_bandwidth; - uint8_t prs_cyclic_prefix_type; - uint8_t prs_muting; -} nfapi_dl_config_prs_pdu_rel9_t; -#define NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG 0x200A - -typedef struct { - nfapi_dl_config_prs_pdu_rel9_t prs_pdu_rel9; -} nfapi_dl_config_prs_pdu; - -typedef struct { - nfapi_tl_t tl; - uint8_t csi_rs_antenna_port_count_r10; - uint8_t csi_rs_resource_config_r10; - uint16_t transmission_power; - uint16_t csi_rs_zero_tx_power_resource_config_bitmap_r10; - uint8_t csi_rs_number_of_nzp_configuration; - uint8_t csi_rs_resource_config[NFAPI_MAX_CSI_RS_RESOURCE_CONFIG]; -} nfapi_dl_config_csi_rs_pdu_rel10_t; -#define NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG 0x200B - -typedef struct { - nfapi_tl_t tl; - uint8_t csi_rs_class; - uint8_t cdm_type; - uint8_t num_bf_vector; - struct { - uint8_t csi_rs_resource_index; - uint16_t bf_value[NFAPI_MAX_ANTENNA_PORT_COUNT]; - } bf_vector[NFAPI_MAX_BF_VECTORS]; - -}nfapi_dl_config_csi_rs_pdu_rel13_t; -#define NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG 0x2040 - -typedef struct { - nfapi_dl_config_csi_rs_pdu_rel10_t csi_rs_pdu_rel10; - nfapi_dl_config_csi_rs_pdu_rel13_t csi_rs_pdu_rel13; -} nfapi_dl_config_csi_rs_pdu; - -#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG 0x2001 -#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG 0x2002 -#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG 0x2003 -#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG 0x2039 -#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG 0x203a -#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG 0x203b - -typedef struct { - nfapi_tl_t tl; - uint8_t epdcch_resource_assignment_flag; - uint16_t epdcch_id; - uint8_t epdcch_start_symbol; - uint8_t epdcch_num_prb; - uint8_t epdcch_prb_index[NFAPI_MAX_EPDCCH_PRB]; - nfapi_bf_vector_t bf_vector; -} nfapi_dl_config_epdcch_parameters_rel11_t; -#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG 0x2041 - -typedef struct { - nfapi_tl_t tl; - uint8_t dwpts_symbols; - uint8_t initial_lbt_sf; -} nfapi_dl_config_epdcch_parameters_rel13_t; -#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG 0x2042 - -typedef struct { - nfapi_dl_config_dci_dl_pdu_rel8_t epdcch_pdu_rel8; - nfapi_dl_config_dci_dl_pdu_rel9_t epdcch_pdu_rel9; - nfapi_dl_config_dci_dl_pdu_rel10_t epdcch_pdu_rel10; - nfapi_dl_config_dci_dl_pdu_rel11_t epdcch_pdu_rel11; - nfapi_dl_config_dci_dl_pdu_rel12_t epdcch_pdu_rel12; - nfapi_dl_config_dci_dl_pdu_rel13_t epdcch_pdu_rel13; - nfapi_dl_config_epdcch_parameters_rel11_t epdcch_params_rel11; - nfapi_dl_config_epdcch_parameters_rel13_t epdcch_params_rel13; -} nfapi_dl_config_epdcch_pdu; - - -typedef struct { - nfapi_tl_t tl; - uint8_t mpdcch_narrow_band; - uint8_t number_of_prb_pairs; - uint8_t resource_block_assignment; - uint8_t mpdcch_tansmission_type; - uint8_t start_symbol; - uint8_t ecce_index; - uint8_t aggregation_level; - uint8_t rnti_type; - uint16_t rnti; - uint8_t ce_mode; - uint16_t drms_scrambling_init; - uint16_t initial_transmission_sf_io; - uint16_t transmission_power; - uint8_t dci_format; - uint16_t resource_block_coding; - uint8_t mcs; - uint8_t pdsch_reptition_levels; - uint8_t redundancy_version; - uint8_t new_data_indicator; - uint8_t harq_process; - uint8_t tpmi_length; - uint8_t tpmi; - uint8_t pmi_flag; - uint8_t pmi; - uint8_t harq_resource_offset; - uint8_t dci_subframe_repetition_number; - uint8_t tpc; - uint8_t downlink_assignment_index_length; - uint8_t downlink_assignment_index; - uint8_t allocate_prach_flag; - uint8_t preamble_index; - uint8_t prach_mask_index; - uint8_t starting_ce_level; - uint8_t srs_request; - uint8_t antenna_ports_and_scrambling_identity_flag; - uint8_t antenna_ports_and_scrambling_identity; - uint8_t frequency_hopping_enabled_flag; - uint8_t paging_direct_indication_differentiation_flag; - uint8_t direct_indication; - uint8_t total_dci_length_including_padding; - uint8_t number_of_tx_antenna_ports; - uint16_t precoding_value[NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS]; -} nfapi_dl_config_mpdcch_pdu_rel13_t; -#define NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG 0x205B - - -typedef struct { - nfapi_dl_config_mpdcch_pdu_rel13_t mpdcch_pdu_rel13; -} nfapi_dl_config_mpdcch_pdu; - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t pdu_index; - uint16_t transmission_power; - uint16_t hyper_sfn_2_lsbs; -} nfapi_dl_config_nbch_pdu_rel13_t; - -#define NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG 0x205C - -typedef struct { - nfapi_dl_config_nbch_pdu_rel13_t nbch_pdu_rel13; -} nfapi_dl_config_nbch_pdu; - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t pdu_index; - uint8_t ncce_index; - uint8_t aggregation_level; - uint8_t start_symbol; - uint8_t rnti_type; - uint16_t rnti; - uint8_t scrambling_reinitialization_batch_index; - uint8_t nrs_antenna_ports_assumed_by_the_ue; - uint8_t dci_format; - uint8_t scheduling_delay; - uint8_t resource_assignment; - uint8_t repetition_number; - uint8_t mcs; - uint8_t new_data_indicator; - uint8_t harq_ack_resource; - uint8_t npdcch_order_indication; - uint8_t starting_number_of_nprach_repetitions; - uint8_t subcarrier_indication_of_nprach; - uint8_t paging_direct_indication_differentation_flag; - uint8_t direct_indication; - uint8_t dci_subframe_repetition_number; - uint8_t total_dci_length_including_padding; -} nfapi_dl_config_npdcch_pdu_rel13_t; - -#define NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG 0x205D - -typedef struct { - nfapi_dl_config_npdcch_pdu_rel13_t npdcch_pdu_rel13; -} nfapi_dl_config_npdcch_pdu; - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t pdu_index; - uint8_t start_symbol; - uint8_t rnti_type; - uint16_t rnti; - uint16_t resource_assignment; - uint16_t repetition_number; - uint8_t modulation; - uint8_t number_of_subframes_for_resource_assignment; - uint8_t scrambling_sequence_initialization_cinit; - uint16_t sf_idx; - uint8_t nrs_antenna_ports_assumed_by_the_ue; -} nfapi_dl_config_ndlsch_pdu_rel13_t; - -#define NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG 0x205E - -typedef struct { - nfapi_dl_config_ndlsch_pdu_rel13_t ndlsch_pdu_rel13; -} nfapi_dl_config_ndlsch_pdu; - - -typedef struct { - uint8_t pdu_type; - uint8_t pdu_size; - union { - nfapi_dl_config_dci_dl_pdu dci_dl_pdu; - nfapi_dl_config_bch_pdu bch_pdu; - nfapi_dl_config_mch_pdu mch_pdu; - nfapi_dl_config_dlsch_pdu dlsch_pdu; - nfapi_dl_config_pch_pdu pch_pdu; - nfapi_dl_config_prs_pdu prs_pdu; - nfapi_dl_config_csi_rs_pdu csi_rs_pdu; - nfapi_dl_config_epdcch_pdu epdcch_pdu; - nfapi_dl_config_mpdcch_pdu mpdcch_pdu; - nfapi_dl_config_nbch_pdu nbch_pdu; - nfapi_dl_config_npdcch_pdu npdcch_pdu; - nfapi_dl_config_ndlsch_pdu ndlsch_pdu; - }; -} nfapi_dl_config_request_pdu_t; - -#define NFAPI_DL_CONFIG_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint8_t number_pdcch_ofdm_symbols; - uint8_t number_dci; - uint16_t number_pdu; - uint8_t number_pdsch_rnti; - uint16_t transmission_power_pcfich; - nfapi_dl_config_request_pdu_t* dl_config_pdu_list; -} nfapi_dl_config_request_body_t; -#define NFAPI_DL_CONFIG_REQUEST_BODY_TAG 0x2000 - -typedef struct { - nfapi_tl_t tl; - uint32_t handle; - uint16_t size; - uint16_t rnti; - uint8_t resource_block_start; - uint8_t number_of_resource_blocks; - uint8_t modulation_type; - uint8_t cyclic_shift_2_for_drms; - uint8_t frequency_hopping_enabled_flag; - uint8_t frequency_hopping_bits; - uint8_t new_data_indication; - uint8_t redundancy_version; - uint8_t harq_process_number; - uint8_t ul_tx_mode; - uint8_t current_tx_nb; - uint8_t n_srs; -} nfapi_ul_config_ulsch_pdu_rel8_t; -#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG 0x200D - -typedef struct { - nfapi_tl_t tl; - uint8_t resource_allocation_type; - uint32_t resource_block_coding; - uint8_t transport_blocks; - uint8_t transmission_scheme; - uint8_t number_of_layers; - uint8_t codebook_index; - uint8_t disable_sequence_hopping_flag; -} nfapi_ul_config_ulsch_pdu_rel10_t; -#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG 0x200E - - -typedef struct { - nfapi_tl_t tl; - uint8_t virtual_cell_id_enabled_flag; - uint16_t npusch_identity; - uint8_t dmrs_config_flag; - uint16_t ndmrs_csh_identity; -} nfapi_ul_config_ulsch_pdu_rel11_t; - -#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG 0x2043 - -typedef struct { - nfapi_tl_t tl; - uint8_t ue_type; - uint16_t total_number_of_repetitions; - uint16_t repetition_number; - uint16_t initial_transmission_sf_io; - uint8_t empty_symbols_due_to_re_tunning; -} nfapi_ul_config_ulsch_pdu_rel13_t; -#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG 0x2044 - -typedef struct { - nfapi_ul_config_ulsch_pdu_rel8_t ulsch_pdu_rel8; - nfapi_ul_config_ulsch_pdu_rel10_t ulsch_pdu_rel10; - nfapi_ul_config_ulsch_pdu_rel11_t ulsch_pdu_rel11; - nfapi_ul_config_ulsch_pdu_rel13_t ulsch_pdu_rel13; -} nfapi_ul_config_ulsch_pdu; - -typedef struct { - nfapi_tl_t tl; - uint8_t dl_cqi_pmi_size_rank_1; - uint8_t dl_cqi_pmi_size_rank_greater_1; - uint8_t ri_size; - uint8_t delta_offset_cqi; - uint8_t delta_offset_ri; -} nfapi_ul_config_cqi_ri_information_rel8_t; -#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG 0x2010 - -typedef struct { - uint8_t dl_cqi_pmi_ri_size; - uint8_t control_type; -} nfapi_ul_config_periodic_cqi_pmi_ri_report_t; - -typedef struct { - uint8_t number_of_cc; - struct { - uint8_t ri_size; - uint8_t dl_cqi_pmi_size[8]; - } cc[NFAPI_MAX_CC]; -} nfapi_ul_config_aperiodic_cqi_pmi_ri_report_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t report_type; - uint8_t delta_offset_cqi; - uint8_t delta_offset_ri; - union { - nfapi_ul_config_periodic_cqi_pmi_ri_report_t periodic_cqi_pmi_ri_report; - nfapi_ul_config_aperiodic_cqi_pmi_ri_report_t aperiodic_cqi_pmi_ri_report; - }; -} nfapi_ul_config_cqi_ri_information_rel9_t; -#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG 0x2011 - -typedef struct { - uint16_t dl_cqi_pmi_ri_size_2; -} nfapi_ul_config_periodic_cqi_pmi_ri_report_re13_t; - -typedef struct { -} nfapi_ul_config_aperiodic_cqi_pmi_ri_report_re13_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t report_type; // Convience parameter, not sent on the wire - union { - nfapi_ul_config_periodic_cqi_pmi_ri_report_re13_t periodic_cqi_pmi_ri_report; - nfapi_ul_config_aperiodic_cqi_pmi_ri_report_re13_t aperiodic_cqi_pmi_ri_report; - }; -} nfapi_ul_config_cqi_ri_information_rel13_t; -#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG 0x2045 - -typedef struct { - nfapi_ul_config_cqi_ri_information_rel8_t cqi_ri_information_rel8; - nfapi_ul_config_cqi_ri_information_rel9_t cqi_ri_information_rel9; - nfapi_ul_config_cqi_ri_information_rel13_t cqi_ri_information_rel13; -} nfapi_ul_config_cqi_ri_information; - -typedef struct { - nfapi_tl_t tl; - uint8_t harq_size; - uint8_t delta_offset_harq; - uint8_t ack_nack_mode; -} nfapi_ul_config_ulsch_harq_information_rel10_t; -#define NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG 0x2012 - -typedef struct { - nfapi_tl_t tl; - uint16_t harq_size_2; - uint8_t delta_offset_harq_2; -} nfapi_ul_config_ulsch_harq_information_rel13_t; -#define NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG 0x2046 - -typedef struct { - nfapi_ul_config_ulsch_harq_information_rel10_t harq_information_rel10; - nfapi_ul_config_ulsch_harq_information_rel13_t harq_information_rel13; -} nfapi_ul_config_ulsch_harq_information; - -typedef struct { - nfapi_tl_t tl; - uint8_t n_srs_initial; - uint8_t initial_number_of_resource_blocks; -} nfapi_ul_config_initial_transmission_parameters_rel8_t; -#define NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG 0x200F - -typedef struct { - nfapi_ul_config_initial_transmission_parameters_rel8_t initial_transmission_parameters_rel8; -} nfapi_ul_config_initial_transmission_parameters; - -typedef struct { - nfapi_ul_config_ulsch_pdu ulsch_pdu; - nfapi_ul_config_cqi_ri_information cqi_ri_information; - nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters; -} nfapi_ul_config_ulsch_cqi_ri_pdu; - -typedef struct { - nfapi_ul_config_ulsch_pdu ulsch_pdu; - nfapi_ul_config_ulsch_harq_information harq_information; - nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters; -} nfapi_ul_config_ulsch_harq_pdu; - -typedef struct { - nfapi_ul_config_ulsch_pdu ulsch_pdu; - nfapi_ul_config_cqi_ri_information cqi_ri_information; - nfapi_ul_config_ulsch_harq_information harq_information; - nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters; -} nfapi_ul_config_ulsch_cqi_harq_ri_pdu; - - -typedef struct { - nfapi_tl_t tl; - uint32_t handle; - uint16_t rnti; -} nfapi_ul_config_ue_information_rel8_t; -#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG 0x2013 - -typedef struct { - nfapi_tl_t tl; - uint8_t virtual_cell_id_enabled_flag; - uint16_t npusch_identity; -} nfapi_ul_config_ue_information_rel11_t; - -#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG 0x2047 - -typedef struct { - nfapi_tl_t tl; - uint8_t ue_type; - uint8_t empty_symbols; - uint16_t total_number_of_repetitions; - uint16_t repetition_number; -} nfapi_ul_config_ue_information_rel13_t; - -#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG 0x2048 - -typedef struct { - nfapi_ul_config_ue_information_rel8_t ue_information_rel8; - nfapi_ul_config_ue_information_rel11_t ue_information_rel11; - nfapi_ul_config_ue_information_rel13_t ue_information_rel13; -} nfapi_ul_config_ue_information; - -typedef struct { - nfapi_tl_t tl; - uint16_t pucch_index; - uint8_t dl_cqi_pmi_size; -} nfapi_ul_config_cqi_information_rel8_t; -#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG 0x2014 - -typedef struct { - nfapi_tl_t tl; - uint8_t number_of_pucch_resource; - uint16_t pucch_index_p1; -} nfapi_ul_config_cqi_information_rel10_t; -#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG 0x2015 - -typedef struct { - nfapi_tl_t tl; - uint8_t csi_mode; - uint16_t dl_cqi_pmi_size_2; - uint8_t starting_prb; - uint8_t n_prb; - uint8_t cdm_index; - uint8_t n_srs; -} nfapi_ul_config_cqi_information_rel13_t; -#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG 0x2049 - -typedef struct { - nfapi_ul_config_cqi_information_rel8_t cqi_information_rel8; - nfapi_ul_config_cqi_information_rel10_t cqi_information_rel10; - nfapi_ul_config_cqi_information_rel13_t cqi_information_rel13; -} nfapi_ul_config_cqi_information; - -typedef struct { - nfapi_tl_t tl; - uint16_t pucch_index; -} nfapi_ul_config_sr_information_rel8_t; -#define NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG 0x2016 - -typedef struct { - nfapi_tl_t tl; - uint8_t number_of_pucch_resources; - uint16_t pucch_index_p1; -} nfapi_ul_config_sr_information_rel10_t; -#define NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG 0x2017 - -typedef struct { - nfapi_ul_config_sr_information_rel8_t sr_information_rel8; - nfapi_ul_config_sr_information_rel10_t sr_information_rel10; -} nfapi_ul_config_sr_information; - -typedef struct { - nfapi_tl_t tl; - uint8_t harq_size; - uint8_t ack_nack_mode; - uint8_t number_of_pucch_resources; - uint16_t n_pucch_1_0; - uint16_t n_pucch_1_1; - uint16_t n_pucch_1_2; - uint16_t n_pucch_1_3; -} nfapi_ul_config_harq_information_rel10_tdd_t; -#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG 0x2018 - - -typedef struct { - nfapi_tl_t tl; - uint16_t n_pucch_1_0; - uint8_t harq_size; -} nfapi_ul_config_harq_information_rel8_fdd_t; -#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG 0x2019 - -typedef struct { - nfapi_tl_t tl; - uint8_t harq_size; - uint8_t ack_nack_mode; - uint8_t number_of_pucch_resources; - uint16_t n_pucch_1_0; - uint16_t n_pucch_1_1; - uint16_t n_pucch_1_2; - uint16_t n_pucch_1_3; -} nfapi_ul_config_harq_information_rel9_fdd_t; -#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG 0x201a - -typedef struct { - nfapi_tl_t tl; - uint8_t num_ant_ports; - uint16_t n_pucch_2_0; - uint16_t n_pucch_2_1; - uint16_t n_pucch_2_2; - uint16_t n_pucch_2_3; -} nfapi_ul_config_harq_information_rel11_t; -#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG 0x204A - -typedef struct { - nfapi_tl_t tl; - uint16_t harq_size_2; - uint8_t starting_prb; - uint8_t n_prb; - uint8_t cdm_index; - uint8_t n_srs; -} nfapi_ul_config_harq_information_rel13_t; -#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG 0x204B - -typedef struct { - nfapi_ul_config_harq_information_rel10_tdd_t harq_information_rel10_tdd; - nfapi_ul_config_harq_information_rel8_fdd_t harq_information_rel8_fdd; - nfapi_ul_config_harq_information_rel9_fdd_t harq_information_rel9_fdd; - nfapi_ul_config_harq_information_rel11_t harq_information_rel11; - nfapi_ul_config_harq_information_rel13_t harq_information_rel13; -} nfapi_ul_config_harq_information; - -typedef struct { - nfapi_tl_t tl; - uint32_t handle; - uint16_t size; - uint16_t rnti; - uint8_t srs_bandwidth; - uint8_t frequency_domain_position; - uint8_t srs_hopping_bandwidth; - uint8_t transmission_comb; - uint16_t i_srs; - uint8_t sounding_reference_cyclic_shift; -} nfapi_ul_config_srs_pdu_rel8_t; -#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG 0x201b - -typedef struct { - nfapi_tl_t tl; - uint8_t antenna_port; -} nfapi_ul_config_srs_pdu_rel10_t; -#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG 0x201c - -typedef struct { - nfapi_tl_t tl; - uint8_t number_of_combs; -} nfapi_ul_config_srs_pdu_rel13_t; -#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG 0x204c - -typedef struct { - nfapi_ul_config_srs_pdu_rel8_t srs_pdu_rel8; - nfapi_ul_config_srs_pdu_rel10_t srs_pdu_rel10; - nfapi_ul_config_srs_pdu_rel13_t srs_pdu_rel13; -} nfapi_ul_config_srs_pdu; - -typedef struct { - nfapi_ul_config_ue_information ue_information; - nfapi_ul_config_cqi_information cqi_information; -} nfapi_ul_config_uci_cqi_pdu; - -typedef struct { - nfapi_ul_config_ue_information ue_information; - nfapi_ul_config_sr_information sr_information; -} nfapi_ul_config_uci_sr_pdu; - -typedef struct { - nfapi_ul_config_ue_information ue_information; - nfapi_ul_config_harq_information harq_information; -} nfapi_ul_config_uci_harq_pdu; - -typedef struct { - nfapi_ul_config_ue_information ue_information; - nfapi_ul_config_sr_information sr_information; - nfapi_ul_config_harq_information harq_information; -} nfapi_ul_config_uci_sr_harq_pdu; - -typedef struct { - nfapi_ul_config_ue_information ue_information; - nfapi_ul_config_cqi_information cqi_information; - nfapi_ul_config_harq_information harq_information; -} nfapi_ul_config_uci_cqi_harq_pdu; - -typedef struct { - nfapi_ul_config_ue_information ue_information; - nfapi_ul_config_cqi_information cqi_information; - nfapi_ul_config_sr_information sr_information; -} nfapi_ul_config_uci_cqi_sr_pdu; - -typedef struct { - nfapi_ul_config_ue_information ue_information; - nfapi_ul_config_cqi_information cqi_information; - nfapi_ul_config_sr_information sr_information; - nfapi_ul_config_harq_information harq_information; -} nfapi_ul_config_uci_cqi_sr_harq_pdu; - -typedef struct { - nfapi_ul_config_ue_information ue_information; -} nfapi_ul_config_harq_buffer_pdu; - -typedef struct { - nfapi_ul_config_ulsch_pdu ulsch_pdu; - nfapi_ul_config_cqi_information csi_information; -} nfapi_ul_config_ulsch_uci_csi_pdu; - -typedef struct { - nfapi_ul_config_ulsch_pdu ulsch_pdu; - nfapi_ul_config_harq_information harq_information; -} nfapi_ul_config_ulsch_uci_harq_pdu; - -typedef struct { - nfapi_ul_config_ulsch_pdu ulsch_pdu; - nfapi_ul_config_cqi_information csi_information; - nfapi_ul_config_harq_information harq_information; -} nfapi_ul_config_ulsch_csi_uci_harq_pdu; - -typedef struct { - nfapi_tl_t tl; - uint8_t harq_ack_resource; -} nfapi_ul_config_nb_harq_information_rel13_fdd_t; -#define NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG 0x2061 - -typedef struct { - nfapi_ul_config_nb_harq_information_rel13_fdd_t nb_harq_information_rel13_fdd; -} nfapi_ul_config_nb_harq_information; - -typedef struct { - nfapi_tl_t tl; - uint8_t nulsch_format; - uint32_t handle; - uint16_t size; - uint16_t rnti; - uint8_t subcarrier_indication; - uint8_t resource_assignment; - uint8_t mcs; - uint8_t redudancy_version; - uint8_t repetition_number; - uint8_t new_data_indication; - uint8_t n_srs; - uint16_t scrambling_sequence_initialization_cinit; - uint16_t sf_idx; - nfapi_ul_config_ue_information ue_information; - nfapi_ul_config_nb_harq_information nb_harq_information; -} nfapi_ul_config_nulsch_pdu_rel13_t; -#define NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG 0x205F - -typedef struct { - nfapi_ul_config_nulsch_pdu_rel13_t nulsch_pdu_rel13; -} nfapi_ul_config_nulsch_pdu; - - -typedef struct { - nfapi_tl_t tl; - uint8_t nprach_config_0; - uint8_t nprach_config_1; - uint8_t nprach_config_2; -} nfapi_ul_config_nrach_pdu_rel13_t; -#define NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG 0x2067 - -typedef struct { - nfapi_ul_config_nrach_pdu_rel13_t nrach_pdu_rel13; -} nfapi_ul_config_nrach_pdu; - -typedef struct { - uint8_t pdu_type; - uint8_t pdu_size; - union { - nfapi_ul_config_ulsch_pdu ulsch_pdu; - nfapi_ul_config_ulsch_cqi_ri_pdu ulsch_cqi_ri_pdu; - nfapi_ul_config_ulsch_harq_pdu ulsch_harq_pdu; - nfapi_ul_config_ulsch_cqi_harq_ri_pdu ulsch_cqi_harq_ri_pdu; - nfapi_ul_config_uci_cqi_pdu uci_cqi_pdu; - nfapi_ul_config_uci_sr_pdu uci_sr_pdu; - nfapi_ul_config_uci_harq_pdu uci_harq_pdu; - nfapi_ul_config_uci_sr_harq_pdu uci_sr_harq_pdu; - nfapi_ul_config_uci_cqi_harq_pdu uci_cqi_harq_pdu; - nfapi_ul_config_uci_cqi_sr_pdu uci_cqi_sr_pdu; - nfapi_ul_config_uci_cqi_sr_harq_pdu uci_cqi_sr_harq_pdu; - nfapi_ul_config_srs_pdu srs_pdu; - nfapi_ul_config_harq_buffer_pdu harq_buffer_pdu; - nfapi_ul_config_ulsch_uci_csi_pdu ulsch_uci_csi_pdu; - nfapi_ul_config_ulsch_uci_harq_pdu ulsch_uci_harq_pdu; - nfapi_ul_config_ulsch_csi_uci_harq_pdu ulsch_csi_uci_harq_pdu; - nfapi_ul_config_nulsch_pdu nulsch_pdu; - nfapi_ul_config_nrach_pdu nrach_pdu; - }; -} nfapi_ul_config_request_pdu_t; - -#define NFAPI_UL_CONFIG_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint8_t number_of_pdus; - uint8_t rach_prach_frequency_resources; - uint8_t srs_present; - nfapi_ul_config_request_pdu_t* ul_config_pdu_list; -} nfapi_ul_config_request_body_t; -#define NFAPI_UL_CONFIG_REQUEST_BODY_TAG 0x200C - -typedef struct { - nfapi_tl_t tl; - uint8_t resource_block_start; - uint8_t cyclic_shift_2_for_drms; - uint8_t hi_value; - uint8_t i_phich; - uint16_t transmission_power; -} nfapi_hi_dci0_hi_pdu_rel8_t; -#define NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG 0x201e - -typedef struct { - nfapi_tl_t tl; - uint8_t flag_tb2; - uint8_t hi_value_2; -} nfapi_hi_dci0_hi_pdu_rel10_t; -#define NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG 0x201f - -typedef struct { - nfapi_hi_dci0_hi_pdu_rel8_t hi_pdu_rel8; - nfapi_hi_dci0_hi_pdu_rel10_t hi_pdu_rel10; -} nfapi_hi_dci0_hi_pdu; - -typedef struct { - nfapi_tl_t tl; - uint8_t dci_format; - uint8_t cce_index; - uint8_t aggregation_level; - uint16_t rnti; - uint8_t resource_block_start; - uint8_t number_of_resource_block; - uint8_t mcs_1; - uint8_t cyclic_shift_2_for_drms; - uint8_t frequency_hopping_enabled_flag; - uint8_t frequency_hopping_bits; - uint8_t new_data_indication_1; - uint8_t ue_tx_antenna_seleciton; - uint8_t tpc; - uint8_t cqi_csi_request; - uint8_t ul_index; - uint8_t dl_assignment_index; - uint32_t tpc_bitmap; - uint16_t transmission_power; -} nfapi_hi_dci0_dci_pdu_rel8_t; -#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG 0x2020 - -typedef struct { - nfapi_tl_t tl; - uint8_t cross_carrier_scheduling_flag; - uint8_t carrier_indicator; - uint8_t size_of_cqi_csi_feild; - uint8_t srs_flag; - uint8_t srs_request; - uint8_t resource_allocation_flag; - uint8_t resource_allocation_type; - uint32_t resource_block_coding; - uint8_t mcs_2; - uint8_t new_data_indication_2; - uint8_t number_of_antenna_ports; - uint8_t tpmi; - uint8_t total_dci_length_including_padding; - uint8_t n_ul_rb; -} nfapi_hi_dci0_dci_pdu_rel10_t; -#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG 0x2021 - -typedef struct { - nfapi_tl_t tl; - uint8_t pscch_resource; - uint8_t time_resource_pattern; -} nfapi_hi_dci0_dci_pdu_rel12_t; - -#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG 0x204D - -typedef struct { - nfapi_hi_dci0_dci_pdu_rel8_t dci_pdu_rel8; - nfapi_hi_dci0_dci_pdu_rel10_t dci_pdu_rel10; - nfapi_hi_dci0_dci_pdu_rel12_t dci_pdu_rel12; -} nfapi_hi_dci0_dci_pdu; - -typedef nfapi_hi_dci0_dci_pdu_rel8_t nfapi_hi_dci0_epdcch_dci_pdu_rel8_t; -#define NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG 0x2020 - -typedef nfapi_hi_dci0_dci_pdu_rel10_t nfapi_hi_dci0_epdcch_dci_pdu_rel10_t; -#define NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG 0x2021 - -typedef nfapi_dl_config_epdcch_parameters_rel11_t nfapi_hi_dci0_epdcch_parameters_rel11_t; -#define NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG 0x2041 - -typedef struct { - nfapi_hi_dci0_epdcch_dci_pdu_rel8_t epdcch_dci_pdu_rel8; - nfapi_hi_dci0_epdcch_dci_pdu_rel10_t epdcch_dci_pdu_rel10; - nfapi_hi_dci0_epdcch_parameters_rel11_t epdcch_parameters_rel11; -} nfapi_hi_dci0_epdcch_dci_pdu; - - -typedef struct { - nfapi_tl_t tl; - uint8_t mpdcch_narrowband; - uint8_t number_of_prb_pairs; - uint8_t resource_block_assignment; - uint8_t mpdcch_transmission_type; - uint8_t start_symbol; - uint8_t ecce_index; - uint8_t aggreagation_level; - uint8_t rnti_type; - uint16_t rnti; - uint8_t ce_mode; - uint16_t drms_scrambling_init; - uint16_t initial_transmission_sf_io; - uint16_t transmission_power; - uint8_t dci_format; - uint8_t resource_block_start; - uint8_t number_of_resource_blocks; - uint8_t mcs; - uint8_t pusch_repetition_levels; - uint8_t frequency_hopping_flag; - uint8_t new_data_indication; - uint8_t harq_process; - uint8_t redudency_version; - uint8_t tpc; - uint8_t csi_request; - uint8_t ul_inex; - uint8_t dai_presence_flag; - uint8_t dl_assignment_index; - uint8_t srs_request; - uint8_t dci_subframe_repetition_number; - uint32_t tcp_bitmap; - uint8_t total_dci_length_include_padding; - uint8_t number_of_tx_antenna_ports; - uint16_t precoding_value[NFAPI_MAX_ANTENNA_PORT_COUNT]; -} nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t; -#define NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG 0x204E - -typedef struct { - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t mpdcch_dci_pdu_rel13; -} nfapi_hi_dci0_mpdcch_dci_pdu; - -typedef struct { - nfapi_tl_t tl; - uint8_t ncce_index; - uint8_t aggregation_level; - uint8_t start_symbol; - uint16_t rnti; - uint8_t scrambling_reinitialization_batch_index; - uint8_t nrs_antenna_ports_assumed_by_the_ue; - uint8_t subcarrier_indication; - uint8_t resource_assignment; - uint8_t scheduling_delay; - uint8_t mcs; - uint8_t redudancy_version; - uint8_t repetition_number; - uint8_t new_data_indicator; - uint8_t dci_subframe_repetition_number; -} nfapi_hi_dci0_npdcch_dci_pdu_rel13_t; - -#define NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG 0x2062 - -typedef struct { - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t npdcch_dci_pdu_rel13; -} nfapi_hi_dci0_npdcch_dci_pdu; - -typedef struct { - uint8_t pdu_type; - uint8_t pdu_size; - union { - nfapi_hi_dci0_hi_pdu hi_pdu; - nfapi_hi_dci0_dci_pdu dci_pdu; - nfapi_hi_dci0_epdcch_dci_pdu epdcch_dci_pdu; - nfapi_hi_dci0_mpdcch_dci_pdu mpdcch_dci_pdu; - nfapi_hi_dci0_npdcch_dci_pdu npdcch_dci_pdu; - }; -} nfapi_hi_dci0_request_pdu_t; - -#define NFAPI_HI_DCI0_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint16_t sfnsf; - uint8_t number_of_dci; - uint8_t number_of_hi; - nfapi_hi_dci0_request_pdu_t* hi_dci0_pdu_list; -} nfapi_hi_dci0_request_body_t; -#define NFAPI_HI_DCI0_REQUEST_BODY_TAG 0x201D - -#define NFAPI_TX_MAX_SEGMENTS 32 -typedef struct { - uint16_t pdu_length; - uint16_t pdu_index; - uint8_t num_segments; - struct { - uint32_t segment_length; - uint8_t* segment_data; - } segments[NFAPI_TX_MAX_SEGMENTS]; -} nfapi_tx_request_pdu_t; - -#define NFAPI_TX_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_pdus; - nfapi_tx_request_pdu_t* tx_pdu_list; -} nfapi_tx_request_body_t; -#define NFAPI_TX_REQUEST_BODY_TAG 0x2022 - -// P7 Message Structures -typedef struct { - nfapi_p7_message_header_t header; - uint32_t t1; - int32_t delta_sfn_sf; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_dl_node_sync_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint32_t t1; - uint32_t t2; - uint32_t t3; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_ul_node_sync_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint32_t last_sfn_sf; - uint32_t time_since_last_timing_info; - uint32_t dl_config_jitter; - uint32_t tx_request_jitter; - uint32_t ul_config_jitter; - uint32_t hi_dci0_jitter; - int32_t dl_config_latest_delay; - int32_t tx_request_latest_delay; - int32_t ul_config_latest_delay; - int32_t hi_dci0_latest_delay; - int32_t dl_config_earliest_arrival; - int32_t tx_request_earliest_arrival; - int32_t ul_config_earliest_arrival; - int32_t hi_dci0_earliest_arrival; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_timing_info_t; - -typedef struct { - nfapi_tl_t tl; - uint32_t handle; - uint16_t rnti; -} nfapi_rx_ue_information; -#define NFAPI_RX_UE_INFORMATION_TAG 0x2038 - -typedef struct { - uint8_t value_0; - uint8_t value_1; -} nfapi_harq_indication_tdd_harq_data_bundling_t; - -typedef struct { - uint8_t value_0; - uint8_t value_1; - uint8_t value_2; - uint8_t value_3; -} nfapi_harq_indication_tdd_harq_data_multiplexing_t; - -typedef struct { - uint8_t value_0; -} nfapi_harq_indication_tdd_harq_data_special_bundling_t; - -typedef struct { - uint8_t value_0; -} nfapi_harq_indication_tdd_harq_data_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t mode; - uint8_t number_of_ack_nack; - union{ - nfapi_harq_indication_tdd_harq_data_bundling_t bundling; - nfapi_harq_indication_tdd_harq_data_multiplexing_t multiplex; - nfapi_harq_indication_tdd_harq_data_special_bundling_t special_bundling; - } harq_data; -} nfapi_harq_indication_tdd_rel8_t; -#define NFAPI_HARQ_INDICATION_TDD_REL8_TAG 0x2027 - -typedef struct { - nfapi_tl_t tl; - uint8_t mode; - uint8_t number_of_ack_nack; - union{ - nfapi_harq_indication_tdd_harq_data_t bundling; - nfapi_harq_indication_tdd_harq_data_t multiplex; - nfapi_harq_indication_tdd_harq_data_special_bundling_t special_bundling; - nfapi_harq_indication_tdd_harq_data_t channel_selection; - nfapi_harq_indication_tdd_harq_data_t format_3; - } harq_data[NFAPI_MAX_NUMBER_ACK_NACK_TDD]; -} nfapi_harq_indication_tdd_rel9_t; -#define NFAPI_HARQ_INDICATION_TDD_REL9_TAG 0x2028 - -typedef struct { - nfapi_tl_t tl; - uint8_t mode; - uint16_t number_of_ack_nack; - union{ - nfapi_harq_indication_tdd_harq_data_t bundling; - nfapi_harq_indication_tdd_harq_data_t multiplex; - nfapi_harq_indication_tdd_harq_data_special_bundling_t special_bundling; - nfapi_harq_indication_tdd_harq_data_t channel_selection; - nfapi_harq_indication_tdd_harq_data_t format_3; - nfapi_harq_indication_tdd_harq_data_t format_4; - nfapi_harq_indication_tdd_harq_data_t format_5; - } harq_data[NFAPI_MAX_NUMBER_ACK_NACK_TDD]; -} nfapi_harq_indication_tdd_rel13_t; -#define NFAPI_HARQ_INDICATION_TDD_REL13_TAG 0x204F - -typedef struct { - nfapi_tl_t tl; - uint8_t harq_tb1; - uint8_t harq_tb2; -} nfapi_harq_indication_fdd_rel8_t; -#define NFAPI_HARQ_INDICATION_FDD_REL8_TAG 0x2029 - -#define NFAPI_HARQ_ACK_NACK_REL9_MAX 10 -typedef struct { - nfapi_tl_t tl; - uint8_t mode; - uint8_t number_of_ack_nack; - uint8_t harq_tb_n[NFAPI_HARQ_ACK_NACK_REL9_MAX]; -} nfapi_harq_indication_fdd_rel9_t; -#define NFAPI_HARQ_INDICATION_FDD_REL9_TAG 0x202a - -#define NFAPI_HARQ_ACK_NACK_REL13_MAX 22 // Need to check this max? -typedef struct { - nfapi_tl_t tl; - uint8_t mode; - uint16_t number_of_ack_nack; - uint8_t harq_tb_n[NFAPI_HARQ_ACK_NACK_REL13_MAX]; -} nfapi_harq_indication_fdd_rel13_t; -#define NFAPI_HARQ_INDICATION_FDD_REL13_TAG 0x2050 - -typedef struct { - nfapi_tl_t tl; - uint8_t ul_cqi; - uint8_t channel; -} nfapi_ul_cqi_information_t; -#define NFAPI_UL_CQI_INFORMATION_TAG 0x2052 - -// Only expect 1 harq_indication TLV.tag to be set -// Would this be a better a an union, but not clear which combinations -// are valid -typedef struct { - uint16_t instance_length; - nfapi_rx_ue_information rx_ue_information; - nfapi_harq_indication_tdd_rel8_t harq_indication_tdd_rel8; - nfapi_harq_indication_tdd_rel9_t harq_indication_tdd_rel9; - nfapi_harq_indication_tdd_rel13_t harq_indication_tdd_rel13; - nfapi_harq_indication_fdd_rel8_t harq_indication_fdd_rel8; - nfapi_harq_indication_fdd_rel9_t harq_indication_fdd_rel9; - nfapi_harq_indication_fdd_rel13_t harq_indication_fdd_rel13; - nfapi_ul_cqi_information_t ul_cqi_information; -} nfapi_harq_indication_pdu_t; - -#define NFAPI_HARQ_IND_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_harqs; - nfapi_harq_indication_pdu_t* harq_pdu_list; -} nfapi_harq_indication_body_t; -#define NFAPI_HARQ_INDICATION_BODY_TAG 0x2026 - -typedef struct { - nfapi_tl_t tl; - uint8_t crc_flag; -} nfapi_crc_indication_rel8_t; -#define NFAPI_CRC_INDICATION_REL8_TAG 0x202c - -typedef struct { - uint16_t instance_length; - nfapi_rx_ue_information rx_ue_information; - nfapi_crc_indication_rel8_t crc_indication_rel8; -} nfapi_crc_indication_pdu_t; - -#define NFAPI_CRC_IND_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_crcs; - nfapi_crc_indication_pdu_t* crc_pdu_list; -} nfapi_crc_indication_body_t; -#define NFAPI_CRC_INDICATION_BODY_TAG 0x202b - -typedef struct { - uint16_t instance_length; - nfapi_rx_ue_information rx_ue_information; - nfapi_ul_cqi_information_t ul_cqi_information; -} nfapi_sr_indication_pdu_t; - -#define NFAPI_SR_IND_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_srs; // Question : should this be srs - nfapi_sr_indication_pdu_t* sr_pdu_list; -} nfapi_sr_indication_body_t; -#define NFAPI_SR_INDICATION_BODY_TAG 0x202d - -// The data offset should be set to 0 or 1 before encoding -// If it is set to 1 the nfapi library will detemine the correct offset - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t data_offset; - uint8_t ul_cqi; - uint8_t ri; - uint16_t timing_advance; -} nfapi_cqi_indication_rel8_t; -#define NFAPI_CQI_INDICATION_REL8_TAG 0x202f - -#define NFAPI_CC_MAX 4 -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t data_offset; - uint8_t ul_cqi; - uint8_t number_of_cc_reported; - uint8_t ri[NFAPI_CC_MAX]; - uint16_t timing_advance; - uint16_t timing_advance_r9; -} nfapi_cqi_indication_rel9_t; -#define NFAPI_CQI_INDICATION_REL9_TAG 0x2030 - -typedef struct { - uint16_t instance_length; - nfapi_rx_ue_information rx_ue_information; - nfapi_cqi_indication_rel8_t cqi_indication_rel8; - nfapi_cqi_indication_rel9_t cqi_indication_rel9; - nfapi_ul_cqi_information_t ul_cqi_information; -} nfapi_cqi_indication_pdu_t; - -#define NFAPI_CQI_RAW_MAX_LEN 12 -typedef struct { - uint8_t pdu[NFAPI_CQI_RAW_MAX_LEN]; -} nfapi_cqi_indication_raw_pdu_t; - -#define NFAPI_CQI_IND_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_cqis; - nfapi_cqi_indication_pdu_t* cqi_pdu_list; - nfapi_cqi_indication_raw_pdu_t* cqi_raw_pdu_list; -} nfapi_cqi_indication_body_t; -#define NFAPI_CQI_INDICATION_BODY_TAG 0x202e - -typedef struct { - nfapi_tl_t tl; - uint16_t rnti; - uint8_t preamble; - uint16_t timing_advance; -} nfapi_preamble_pdu_rel8_t; -#define NFAPI_PREAMBLE_REL8_TAG 0x2032 - -typedef struct { - nfapi_tl_t tl; - uint16_t timing_advance_r9; -} nfapi_preamble_pdu_rel9_t; -#define NFAPI_PREAMBLE_REL9_TAG 0x2033 - -typedef struct { - nfapi_tl_t tl; - uint8_t rach_resource_type; -} nfapi_preamble_pdu_rel13_t; -#define NFAPI_PREAMBLE_REL13_TAG 0x2051 - -typedef struct { - uint16_t instance_length; - nfapi_preamble_pdu_rel8_t preamble_rel8; - nfapi_preamble_pdu_rel9_t preamble_rel9; - nfapi_preamble_pdu_rel13_t preamble_rel13; -} nfapi_preamble_pdu_t; - -#define NFAPI_PREAMBLE_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_preambles; - nfapi_preamble_pdu_t* preamble_list; -} nfapi_rach_indication_body_t; -#define NFAPI_RACH_INDICATION_BODY_TAG 0x2031 - -#define NFAPI_NUM_RB_MAX 1000 -typedef struct { - nfapi_tl_t tl; - uint16_t doppler_estimation; - uint16_t timing_advance; - uint8_t number_of_resource_blocks; - uint8_t rb_start; - uint8_t snr[NFAPI_NUM_RB_MAX]; -} nfapi_srs_indication_fdd_rel8_t; -#define NFAPI_SRS_INDICATION_FDD_REL8_TAG 0x2035 - -typedef struct { - nfapi_tl_t tl; - uint16_t timing_advance_r9; -} nfapi_srs_indication_fdd_rel9_t; -#define NFAPI_SRS_INDICATION_FDD_REL9_TAG 0x2036 - -typedef struct { - nfapi_tl_t tl; - uint8_t uppts_symbol; -} nfapi_srs_indication_ttd_rel10_t; -#define NFAPI_SRS_INDICATION_TDD_REL10_TAG 0x2037 - -typedef struct { - nfapi_tl_t tl; - uint16_t ul_rtoa; -} nfapi_srs_indication_fdd_rel11_t; -#define NFAPI_SRS_INDICATION_FDD_REL11_TAG 0x2053 - - -typedef struct { - nfapi_tl_t tl; - uint8_t num_prb_per_subband; - uint8_t number_of_subbands; - uint8_t num_atennas; - struct { - uint8_t subband_index; - uint16_t channel[NFAPI_MAX_NUM_PHYSICAL_ANTENNAS]; - } subands[NFAPI_MAX_NUM_SUBBANDS]; -} nfapi_tdd_channel_measurement_t; -#define NFAPI_TDD_CHANNEL_MEASUREMENT_TAG 0x2054 - -typedef struct { - uint16_t instance_length; - nfapi_rx_ue_information rx_ue_information; - nfapi_srs_indication_fdd_rel8_t srs_indication_fdd_rel8; - nfapi_srs_indication_fdd_rel9_t srs_indication_fdd_rel9; - nfapi_srs_indication_ttd_rel10_t srs_indication_tdd_rel10; - nfapi_srs_indication_fdd_rel11_t srs_indication_fdd_rel11; - nfapi_tdd_channel_measurement_t tdd_channel_measurement; -} nfapi_srs_indication_pdu_t; - -#define NFAPI_SRS_IND_MAX_PDU 16 -typedef struct { - nfapi_tl_t tl; - uint8_t number_of_ues; - nfapi_srs_indication_pdu_t* srs_pdu_list; -} nfapi_srs_indication_body_t; -#define NFAPI_SRS_INDICATION_BODY_TAG 0x2034 - -typedef struct { - nfapi_tl_t tl; - uint16_t length; - uint16_t offset; - uint8_t ul_cqi; - uint16_t timing_advance; -} nfapi_rx_indication_rel8_t; -#define NFAPI_RX_INDICATION_REL8_TAG 0x2024 - -typedef struct { - nfapi_tl_t tl; - uint16_t timing_advance_r9; - } nfapi_rx_indication_rel9_t; -#define NFAPI_RX_INDICATION_REL9_TAG 0x2025 - -typedef struct { - nfapi_rx_ue_information rx_ue_information; - nfapi_rx_indication_rel8_t rx_indication_rel8; - nfapi_rx_indication_rel9_t rx_indication_rel9; - uint8_t* data; -} nfapi_rx_indication_pdu_t; - -#define NFAPI_RX_IND_MAX_PDU 100 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_pdus; - nfapi_rx_indication_pdu_t* rx_pdu_list; -} nfapi_rx_indication_body_t; -#define NFAPI_RX_INDICATION_BODY_TAG 0x2023 - -typedef struct { - nfapi_tl_t tl; - uint8_t harq_tb1; -} nfapi_nb_harq_indication_fdd_rel13_t; -#define NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG 0x2064 - -typedef struct { - uint16_t instance_length; - nfapi_rx_ue_information rx_ue_information; - nfapi_nb_harq_indication_fdd_rel13_t nb_harq_indication_fdd_rel13; - nfapi_ul_cqi_information_t ul_cqi_information; -} nfapi_nb_harq_indication_pdu_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_harqs; - nfapi_nb_harq_indication_pdu_t* nb_harq_pdu_list; -} nfapi_nb_harq_indication_body_t; -#define NFAPI_NB_HARQ_INDICATION_BODY_TAG 0x2063 - -typedef struct { - nfapi_tl_t tl; - uint16_t rnti; - uint8_t initial_sc; - uint16_t timing_advance; - uint8_t nrach_ce_level; -} nfapi_nrach_indication_pdu_rel13_t; -#define NFAPI_NRACH_INDICATION_REL13_TAG 0x2066 - -typedef struct { - nfapi_nrach_indication_pdu_rel13_t nrach_indication_rel13; -} nfapi_nrach_indication_pdu_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t number_of_initial_scs_detected; - nfapi_nrach_indication_pdu_t* nrach_pdu_list; -} nfapi_nrach_indication_body_t; -#define NFAPI_NRACH_INDICATION_BODY_TAG 0x2065 - -typedef struct { - nfapi_tl_t tl; - uint32_t handle; - uint32_t mp_cca; - uint32_t n_cca; - uint32_t offset; - uint32_t lte_txop_sf; - uint16_t txop_sfn_sf_end; - uint32_t lbt_mode; -} nfapi_lbt_pdsch_req_pdu_rel13_t; -#define NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG 0x2056 - -typedef struct { - nfapi_lbt_pdsch_req_pdu_rel13_t lbt_pdsch_req_pdu_rel13; -} nfapi_lbt_pdsch_req_pdu; - -typedef struct { - nfapi_tl_t tl; - uint32_t handle; - uint32_t offset; - uint16_t sfn_sf_end; - uint32_t lbt_mode; -} nfapi_lbt_drs_req_pdu_rel13_t; -#define NFAPI_LBT_DRS_REQ_PDU_REL13_TAG 0x2057 - -typedef struct { - nfapi_lbt_drs_req_pdu_rel13_t lbt_drs_req_pdu_rel13; -} nfapi_lbt_drs_req_pdu; - -typedef struct { - uint8_t pdu_type; - uint8_t pdu_size; - union { - nfapi_lbt_pdsch_req_pdu lbt_pdsch_req_pdu; - nfapi_lbt_drs_req_pdu lbt_drs_req_pdu; - }; -} nfapi_lbt_dl_config_request_pdu_t; - -#define NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU 16 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_pdus; - nfapi_lbt_dl_config_request_pdu_t* lbt_dl_config_req_pdu_list; -} nfapi_lbt_dl_config_request_body_t; -#define NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG 0x2055 - - -typedef struct { - nfapi_tl_t tl; - uint32_t handle; - uint32_t result; - uint32_t lte_txop_symbols; - uint32_t initial_partial_sf; -} nfapi_lbt_pdsch_rsp_pdu_rel13_t; -#define NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG 0x2059 - -typedef struct { - nfapi_lbt_pdsch_rsp_pdu_rel13_t lbt_pdsch_rsp_pdu_rel13; -} nfapi_lbt_pdsch_rsp_pdu; - -typedef struct { - nfapi_tl_t tl; - uint32_t handle; - uint32_t result; -} nfapi_lbt_drs_rsp_pdu_rel13_t; -#define NFAPI_LBT_DRS_RSP_PDU_REL13_TAG 0x205A - -typedef struct { - nfapi_lbt_drs_rsp_pdu_rel13_t lbt_drs_rsp_pdu_rel13; -} nfapi_lbt_drs_rsp_pdu; - - -typedef struct { - uint8_t pdu_type; - uint8_t pdu_size; - union { - nfapi_lbt_pdsch_rsp_pdu lbt_pdsch_rsp_pdu; - nfapi_lbt_drs_rsp_pdu lbt_drs_rsp_pdu; - }; -} nfapi_lbt_dl_indication_pdu_t; - -#define NFAPI_LBT_IND_MAX_PDU 16 -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_pdus; - nfapi_lbt_dl_indication_pdu_t* lbt_indication_pdu_list; -} nfapi_lbt_dl_indication_body_t; -#define NFAPI_LBT_DL_INDICATION_BODY_TAG 0x2058 - -typedef struct { -} nfapi_error_indication_msg_invalid_state; - -typedef struct { -} nfapi_error_indication_msg_bch_missing; - -typedef struct { - uint16_t recieved_sfn_sf; - uint16_t expected_sfn_sf; -} nfapi_error_indication_sfn_out_of_sync; - -typedef struct { - uint8_t sub_error_code; - uint8_t direction; - uint16_t rnti; - uint8_t pdu_type; -} nfapi_error_indication_msg_pdu_err; - -typedef struct { - uint16_t recieved_sfn_sf; - uint16_t expected_sfn_sf; -} nfapi_error_indication_msg_invalid_sfn; - -typedef struct { - uint8_t sub_error_code; - uint8_t phich_lowest_ul_rb_index; -} nfapi_error_indication_msg_hi_err; - -typedef struct { - uint8_t sub_error_code; - uint16_t pdu_index; -} nfapi_error_indication_msg_tx_err; - -// -// P4 Message Structures -// - -typedef struct { - nfapi_tl_t tl; - uint8_t frequency_band_indicator; - uint16_t measurement_period; - uint8_t bandwidth; - uint32_t timeout; - uint8_t number_of_earfcns; - uint16_t earfcn[NFAPI_MAX_CARRIER_LIST]; -} nfapi_lte_rssi_request_t; - -#define NFAPI_LTE_RSSI_REQUEST_TAG 0x3000 - -#define NFAPI_P4_START_TAG NFAPI_LTE_RSSI_REQUEST_TAG - -typedef struct { - nfapi_tl_t tl; - uint8_t frequency_band_indicator; - uint16_t measurement_period; - uint32_t timeout; - uint8_t number_of_uarfcns; - uint16_t uarfcn[NFAPI_MAX_CARRIER_LIST]; -} nfapi_utran_rssi_request_t; - -#define NFAPI_UTRAN_RSSI_REQUEST_TAG 0x3001 - -typedef struct { - uint16_t arfcn; - uint8_t direction; -} nfapi_arfcn_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t frequency_band_indicator; - uint16_t measurement_period; - uint32_t timeout; - uint8_t number_of_arfcns; - nfapi_arfcn_t arfcn[NFAPI_MAX_CARRIER_LIST]; -} nfapi_geran_rssi_request_t; - -#define NFAPI_GERAN_RSSI_REQUEST_TAG 0x3002 - - - -typedef struct { - uint16_t earfcn; - uint8_t number_of_ro_dl; - uint8_t ro_dl[NFAPI_MAX_RO_DL]; -} nfapi_earfcn_t; - -typedef struct { - nfapi_tl_t tl; - uint8_t frequency_band_indicator; - uint16_t measurement_period; - uint32_t timeout; - uint8_t number_of_earfcns; - nfapi_earfcn_t earfcn[NFAPI_MAX_CARRIER_LIST]; -} nfapi_nb_iot_rssi_request_t; - -#define NFAPI_NB_IOT_RSSI_REQUEST_TAG 0x3020 - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_rssi; - int16_t rssi[NFAPI_MAX_RSSI]; -} nfapi_rssi_indication_body_t; - -#define NFAPI_RSSI_INDICATION_TAG 0x3003 - -typedef struct { - nfapi_tl_t tl; - uint16_t earfcn; - uint8_t measurement_bandwidth; - uint8_t exhaustive_search; - uint32_t timeout; - uint8_t number_of_pci; - uint16_t pci[NFAPI_MAX_PCI_LIST]; -} nfapi_lte_cell_search_request_t; - -#define NFAPI_LTE_CELL_SEARCH_REQUEST_TAG 0x3004 - -typedef struct { - nfapi_tl_t tl; - uint16_t uarfcn; - uint8_t exhaustive_search; - uint32_t timeout; - uint8_t number_of_psc; - uint16_t psc[NFAPI_MAX_PSC_LIST]; -} nfapi_utran_cell_search_request_t; - -#define NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG 0x3005 - -typedef struct { - nfapi_tl_t tl; - uint32_t timeout; - uint8_t number_of_arfcn; - uint16_t arfcn[NFAPI_MAX_ARFCN_LIST]; -} nfapi_geran_cell_search_request_t; - -#define NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG 0x3006 - -typedef struct { - nfapi_tl_t tl; - uint16_t earfcn; - uint8_t ro_dl; - uint8_t exhaustive_search; - uint32_t timeout; - uint8_t number_of_pci; - uint16_t pci[NFAPI_MAX_PCI_LIST]; -} nfapi_nb_iot_cell_search_request_t; - -#define NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG 0x3021 - -typedef struct { - uint16_t pci; - uint8_t rsrp; - uint8_t rsrq; - int16_t frequency_offset; -} nfapi_lte_found_cell_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_lte_cells_found; - nfapi_lte_found_cell_t lte_found_cells[NFAPI_MAX_LTE_CELLS_FOUND]; -} nfapi_lte_cell_search_indication_t; - -#define NFAPI_LTE_CELL_SEARCH_INDICATION_TAG 0x3007 - -typedef struct { - uint16_t psc; - uint8_t rscp; - uint8_t ecno; - int16_t frequency_offset; -} nfapi_utran_found_cell_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_utran_cells_found; - nfapi_utran_found_cell_t utran_found_cells[NFAPI_MAX_UTRAN_CELLS_FOUND]; -} nfapi_utran_cell_search_indication_t; - -#define NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG 0x3008 - -typedef struct { - uint16_t arfcn; - uint8_t bsic; - uint8_t rxlev; - uint8_t rxqual; - int16_t frequency_offset; - uint32_t sfn_offset; -} nfapi_gsm_found_cell_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_gsm_cells_found; - nfapi_gsm_found_cell_t gsm_found_cells[NFAPI_MAX_GSM_CELLS_FOUND]; -} nfapi_geran_cell_search_indication_t; - -#define NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG 0x3009 - -typedef struct { - uint16_t pci; - uint8_t rsrp; - uint8_t rsrq; - int16_t frequency_offset; -} nfapi_nb_iot_found_cell_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t number_of_nb_iot_cells_found; - nfapi_nb_iot_found_cell_t nb_iot_found_cells[NFAPI_MAX_NB_IOT_CELLS_FOUND]; -} nfapi_nb_iot_cell_search_indication_t; - -#define NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG 0x3022 - -typedef nfapi_opaqaue_data_t nfapi_pnf_cell_search_state_t; - -#define NFAPI_PNF_CELL_SEARCH_STATE_TAG 0x300A - -typedef struct { - nfapi_tl_t tl; - uint16_t earfcn; - uint16_t pci; - uint32_t timeout; -} nfapi_lte_broadcast_detect_request_t; - -#define NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG 0x300B - -typedef struct { - nfapi_tl_t tl; - uint16_t uarfcn; - uint16_t psc; - uint32_t timeout; -} nfapi_utran_broadcast_detect_request_t; - -#define NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG 0x300C - -typedef struct { - nfapi_tl_t tl; - uint16_t earfcn; - uint8_t ro_dl; - uint16_t pci; - uint32_t timeout; -} nfapi_nb_iot_broadcast_detect_request_t; - -#define NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG 0x3023 - -typedef struct { - nfapi_tl_t tl; - uint8_t number_of_tx_antenna; - uint16_t mib_length; - uint8_t mib[NFAPI_MAX_MIB_LENGTH]; - uint32_t sfn_offset; -} nfapi_lte_broadcast_detect_indication_t; - -#define NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG 0x300E - -typedef struct { - nfapi_tl_t tl; - uint16_t mib_length; - uint8_t mib[NFAPI_MAX_MIB_LENGTH]; - uint32_t sfn_offset; -} nfapi_utran_broadcast_detect_indication_t; - -#define NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG 0x300F - - -typedef struct { - nfapi_tl_t tl; - uint8_t number_of_tx_antenna; - uint16_t mib_length; - uint8_t mib[NFAPI_MAX_MIB_LENGTH]; - uint32_t sfn_offset; -} nfapi_nb_iot_broadcast_detect_indication_t; - -#define NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG 0x3024 - -#define NFAPI_PNF_CELL_BROADCAST_STATE_TAG 0x3010 - -typedef struct { - nfapi_tl_t tl; - uint16_t earfcn; - uint16_t pci; - uint16_t downlink_channel_bandwidth; - uint8_t phich_configuration; - uint8_t number_of_tx_antenna; - uint8_t retry_count; - uint32_t timeout; -} nfapi_lte_system_information_schedule_request_t; - -#define NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG 0x3011 - - -typedef struct { - nfapi_tl_t tl; - uint16_t earfcn; - uint8_t ro_dl; - uint16_t pci; - uint8_t scheduling_info_sib1_nb; - uint32_t timeout; -} nfapi_nb_iot_system_information_schedule_request_t; - -#define NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG 0x3025 - -typedef nfapi_opaqaue_data_t nfapi_pnf_cell_broadcast_state_t; - -typedef struct { - uint8_t si_periodicity; - uint8_t si_index; -} nfapi_lte_system_information_si_periodicity_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t earfcn; - uint16_t pci; - uint16_t downlink_channel_bandwidth; - uint8_t phich_configuration; - uint8_t number_of_tx_antenna; - uint8_t number_of_si_periodicity; - nfapi_lte_system_information_si_periodicity_t si_periodicity[NFAPI_MAX_SI_PERIODICITY]; - uint8_t si_window_length; - uint32_t timeout; -} nfapi_lte_system_information_request_t; - -#define NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG 0x3014 - -typedef struct { - nfapi_tl_t tl; - uint16_t uarfcn; - uint16_t psc; - uint32_t timeout; -} nfapi_utran_system_information_request_t; - -#define NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG 0x3015 - -typedef struct { - nfapi_tl_t tl; - uint16_t arfcn; - uint8_t bsic; - uint32_t timeout; -} nfapi_geran_system_information_request_t; - -#define NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG 0x3016 - -typedef struct { - uint8_t si_periodicity; - uint8_t si_repetition_pattern; - uint8_t si_tb_size; - uint8_t number_of_si_index; - uint8_t si_index[NFAPI_MAX_SI_INDEX]; -} nfapi_nb_iot_system_information_si_periodicity_t; - -typedef struct { - nfapi_tl_t tl; - uint16_t earfcn; - uint8_t ro_dl; - uint16_t pci; - uint8_t number_of_si_periodicity; - nfapi_nb_iot_system_information_si_periodicity_t si_periodicity[NFAPI_MAX_SI_PERIODICITY]; - uint8_t si_window_length; - uint32_t timeout; -} nfapi_nb_iot_system_information_request_t; - -#define NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG 0x3027 - -typedef struct { - nfapi_tl_t tl; - uint8_t sib_type; - uint16_t sib_length; - uint8_t sib[NFAPI_MAX_SIB_LENGTH]; -} nfapi_lte_system_information_indication_t; - -#define NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG 0x3018 - -typedef struct { - nfapi_tl_t tl; - uint16_t sib_length; - uint8_t sib[NFAPI_MAX_SIB_LENGTH]; -} nfapi_utran_system_information_indication_t; - -#define NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG 0x3019 - -typedef struct { - nfapi_tl_t tl; - uint16_t si_length; - uint8_t si[NFAPI_MAX_SI_LENGTH]; -} nfapi_geran_system_information_indication_t; - -#define NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG 0x301a - -typedef struct { - nfapi_tl_t tl; - uint8_t sib_type; - uint16_t sib_length; - uint8_t sib[NFAPI_MAX_SIB_LENGTH]; -} nfapi_nb_iot_system_information_indication_t; - -#define NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG 0x3026 - - -// -// Top level NFAP messages -// - -// -// P7 -// - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_dl_config_request_body_t dl_config_request_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_dl_config_request_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_ul_config_request_body_t ul_config_request_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_ul_config_request_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_hi_dci0_request_body_t hi_dci0_request_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_hi_dci0_request_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_tx_request_body_t tx_request_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_tx_request_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; -} nfapi_subframe_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_harq_indication_body_t harq_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_harq_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_crc_indication_body_t crc_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_crc_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_sr_indication_body_t sr_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_sr_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_cqi_indication_body_t cqi_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_cqi_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_rach_indication_body_t rach_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_rach_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_srs_indication_body_t srs_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_srs_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_rx_indication_body_t rx_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_rx_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_nb_harq_indication_body_t nb_harq_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nb_harq_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_nrach_indication_body_t nrach_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nrach_indication_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_lbt_dl_config_request_body_t lbt_dl_config_request_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_lbt_dl_config_request_t; - -typedef struct { - nfapi_p7_message_header_t header; - uint16_t sfn_sf; - nfapi_lbt_dl_indication_body_t lbt_dl_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_lbt_dl_indication_t; - - -typedef struct { - nfapi_p7_message_header_t header; - uint8_t message_id; - uint8_t error_code; - union { - nfapi_error_indication_msg_invalid_state msg_invalid_state; - nfapi_error_indication_msg_bch_missing msg_bch_missing; - nfapi_error_indication_sfn_out_of_sync sfn_out_of_sync; - nfapi_error_indication_msg_pdu_err msg_pdu_err; - nfapi_error_indication_msg_invalid_sfn msg_invalid_sfn; - nfapi_error_indication_msg_hi_err msg_hi_err; - nfapi_error_indication_msg_tx_err msg_tx_err; - }; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_error_indication_t; - -// -// P4 Messages -// - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint8_t rat_type; - union { - nfapi_lte_rssi_request_t lte_rssi_request; - nfapi_utran_rssi_request_t utran_rssi_request; - nfapi_geran_rssi_request_t geran_rssi_request; - nfapi_nb_iot_rssi_request_t nb_iot_rssi_request; - }; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_rssi_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_rssi_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_rssi_indication_body_t rssi_indication_body; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_rssi_indication_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint8_t rat_type; - union { - nfapi_lte_cell_search_request_t lte_cell_search_request; - nfapi_utran_cell_search_request_t utran_cell_search_request; - nfapi_geran_cell_search_request_t geran_cell_search_request; - nfapi_nb_iot_cell_search_request_t nb_iot_cell_search_request; - }; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_cell_search_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_cell_search_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_lte_cell_search_indication_t lte_cell_search_indication; - nfapi_utran_cell_search_indication_t utran_cell_search_indication; - nfapi_geran_cell_search_indication_t geran_cell_search_indication; - nfapi_pnf_cell_search_state_t pnf_cell_search_state; - nfapi_nb_iot_cell_search_indication_t nb_iot_cell_search_indication; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_cell_search_indication_t; - - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint8_t rat_type; - union { - nfapi_lte_broadcast_detect_request_t lte_broadcast_detect_request; - nfapi_utran_broadcast_detect_request_t utran_broadcast_detect_request; - nfapi_nb_iot_broadcast_detect_request_t nb_iot_broadcast_detect_request; - }; - nfapi_pnf_cell_search_state_t pnf_cell_search_state; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_broadcast_detect_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_broadcast_detect_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_lte_broadcast_detect_indication_t lte_broadcast_detect_indication; - nfapi_utran_broadcast_detect_indication_t utran_broadcast_detect_indication; - nfapi_nb_iot_broadcast_detect_indication_t nb_iot_broadcast_detect_indication; - nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_broadcast_detect_indication_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint8_t rat_type; - union { - nfapi_lte_system_information_schedule_request_t lte_system_information_schedule_request; - nfapi_nb_iot_system_information_schedule_request_t nb_iot_system_information_schedule_request; - }; - nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_system_information_schedule_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_system_information_schedule_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_lte_system_information_indication_t lte_system_information_indication; - nfapi_nb_iot_system_information_indication_t nb_iot_system_information_indication; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_system_information_schedule_indication_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint8_t rat_type; - union { - nfapi_lte_system_information_request_t lte_system_information_request; - nfapi_utran_system_information_request_t utran_system_information_request; - nfapi_geran_system_information_request_t geran_system_information_request; - nfapi_nb_iot_system_information_request_t nb_iot_system_information_request; - }; - nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_system_information_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_system_information_response_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_lte_system_information_indication_t lte_system_information_indication; - nfapi_utran_system_information_indication_t utran_system_information_indication; - nfapi_geran_system_information_indication_t geran_system_information_indication; - nfapi_nb_iot_system_information_indication_t nb_iot_system_information_indication; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_system_information_indication_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nmm_stop_request_t; - -typedef struct { - nfapi_p4_p5_message_header_t header; - uint32_t error_code; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nmm_stop_response_t; - -// -// Configuration options for the encode decode functions -// - -/*! Configuration options for the p7 pack unpack functions - * - */ -typedef struct nfapi_p7_codec_config { - - /*! Optional call back to allow the user to define the memory allocator. - * \param size The size of the memory to allocate - * \return a pointer to a valid memory block or 0 if it has failed. - * - * If not set the nfapi unpack functions will use malloc - */ - void* (*allocate)(size_t size); - - /*! Optional call back to allow the user to define the memory deallocator. - * \param ptr A poiner to a memory block allocated by the allocate callback - * - * If not set the client should use free - */ - void (*deallocate)(void* ptr); - - /*! Optional call back function to handle unpacking vendor extension tlv. - * \param tl A pointer to a decoded tag length structure - * \param ppReadPackedMsg A handle to the read buffer. - * \param end The end of the read buffer - * \param ve A handle to a vendor extention structure that the call back should allocate if the structure can be decoded - * \param config A pointer to the p7 codec configuration - * \return return 0 if packed successfully, -1 if failed. - * - * If not set the tlv will be skipped - * - * Client should use the help methods in nfapi.h to decode the vendor extention. - * - * \todo Add code example - */ - int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, struct nfapi_p7_codec_config* config); - - /*! Optional call back function to handle packing vendor extension tlv. - * \param ve A pointer to a vendor extention structure. - * \param ppWritePackedMsg A handle to the write buffer - * \param end The end of the write buffer. The callee should make sure not to write beyond the end - * \param config A pointer to the p7 codec configuration - * \return return 0 if packed successfully, -1 if failed. - * - * If not set the the tlv will be skipped - * - * Client should use the help methods in nfapi.h to encode the vendor extention - * - * \todo Add code example - */ - int (*pack_vendor_extension_tlv)(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, struct nfapi_p7_codec_config* config); - - /*! Optional call back function to handle unpacking vendor extension messages. - * \param header A pointer to a decode P7 message header for the vendor extention message - * \param ppReadPackedMsg A handle to the encoded data buffer - * \param end A pointer to the end of the encoded data buffer - * \param config A pointer to the p7 codec configuration - * \return 0 if unpacked successfully, -1 if failed - * - * If not set the message will be ignored - * - * If the message if is unknown the function should return -1 - */ - int (*unpack_p7_vendor_extension)(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, uint8_t *end, struct nfapi_p7_codec_config* config); - - /*! Optional call back function to handle packing vendor extension messages. - * \param header A poiner to a P7 message structure for the venfor extention message - * \param ppWritePackedmsg A handle to the buffer to write the encoded message into - * \param end A pointer to the end of the buffer - * \param cofig A pointer to the p7 codec configuration - * \return 0 if packed successfully, -1 if failed - * - * If not set the the message will be ingored - * - * If the message if is unknown the function should return -1 - */ - int (*pack_p7_vendor_extension)(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedmsg, uint8_t *end, struct nfapi_p7_codec_config* config); - - /*! Optional user data that will be passed back with callbacks - */ - void* user_data; - -} nfapi_p7_codec_config_t; - -/*! Configuration options for the p4 & p5 pack unpack functions - * - */ -typedef struct nfapi_p4_p5_codec_config { - - /*! Optional call back to allow the user to define the memory allocator. - * \param size The size of the memory to allocate - * \return a pointer to a valid memory block or 0 if it has failed. - * - * If not set the nfapi unpack functions will use malloc - */ - void* (*allocate)(size_t size); - - /*! Optional call back to allow the user to define the memory deallocator. - * \param ptr A poiner to a memory block allocated by the allocate callback - * - * If not set free will be used - */ - void (*deallocate)(void* ptr); - - /*! Optional call back function to handle unpacking vendor extension tlv. - * \param tl A pointer to a decoded tag length structure - * \param ppReadPackedMsg A handle to the data buffer to decode - * \param end A pointer to the end of the buffer - * \param ve A handle to a vendor extention structure that will be allocated by this callback - * \param config A pointer to the P4/P5 codec configuration - * \return 0 if unpacked successfully, -1 if failed - * - * If not set the tlv will be skipped - */ - int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, struct nfapi_p4_p5_codec_config* config); - - /*! Optional call back function to handle packing vendor extension tlv. - * \param ve - * \param ppWritePackedMsg A handle to the data buffer pack the tlv into - * \param end A pointer to the end of the buffer - * \param config A pointer to the P4/P5 codec configuration - * \return 0 if packed successfully, -1 if failed - * - * If not set the the tlv will be skipped - */ - int (*pack_vendor_extension_tlv)(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config); - - /*! Optional call back function to handle unpacking vendor extension messages. - * \param header A pointer to a decode P4/P5 message header - * \param ppReadPackgedMsg A handle to the data buffer to decode - * \param end A pointer to the end of the buffer - * \param config A pointer to the P4/P5 codec configuration - * \return 0 if packed successfully, -1 if failed - * - * If not set the message will be ignored - */ - int (*unpack_p4_p5_vendor_extension)(nfapi_p4_p5_message_header_t* header, uint8_t **ppReadPackedMsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config); - - /*! Optional call back function to handle packing vendor extension messages. - * \param header A pointer to the P4/P5 message header to be encoded - * \param ppWritePackedMsg A handle to the data buffer pack the message into - * \param end A pointer to the end of the buffer - * \param config A pointer to the P4/P5 codec configuration - * \return 0 if packed successfully, -1 if failed - * - * If not set the the message will be ingored - */ - int (*pack_p4_p5_vendor_extension)(nfapi_p4_p5_message_header_t* header, uint8_t **ppwritepackedmsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config); - - /*! Optional user data that will be passed back with callbacks - */ - void* user_data; - -} nfapi_p4_p5_codec_config_t; - -// -// Functions -// - -/*! \brief Encodes an NFAPI P4 message to a buffer - * \param pMessageBuf A pointer to a nfapi p4 message structure - * \param messageBufLen The size of the p4 message structure - * \param pPackedBuf A pointer to the buffer that the p4 message will be packed into - * \param packedBufLen The size of the buffer - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will encode a nFAPI P4 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf. - * - */ -int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config); - -/*! \brief Decodes a NFAPI P4 message header - * \param pMessageBuf A pointer to an encoded P4 message header - * \param messageBufLen The size of the encoded P4 message header - * \param pUnpackedBuf A pointer to the nfapi_message_header - * \param unpackedBufLen The size of nfapi_message_header structure. - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p4_p5_message_header structure pointer to by pUnpackedBuf - */ -int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); - -/*! \brief Decodes a NFAPI P4 message - * \param pMessageBuf A pointer to an encoded P4 message - * \param messageBufLen The size of the encoded P4 message - * \param pUnpackedBuf A pointer to the nfapi_message_header - * \param unpackedBufLen The size of nfapi_message_header structure. - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p4 message structure pointer to by pUnpackedBuf - */ -int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); - -/*! \brief Encodes an NFAPI P5 message to a buffer - * \param pMessageBuf A pointer to a nfapi p5 message structure - * \param messageBufLen The size of the p5 message structure - * \param pPackedBuf A pointer to the buffer that the p5 message will be packed into - * \param packedBufLen The size of the buffer - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will encode a nFAPI P5 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf. - * - */ -int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config); - -/*! \brief Decodes an NFAPI P5 message header - * \param pMessageBuf A pointer to an encoded P5 message header - * \param messageBufLen The size of the encoded P5 message header - * \param pUnpackedBuf A pointer to the nfapi_message_header - * \param unpackedBufLen The size of nfapi_message_header structure. - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p4_p5_message_header structure pointer to by pUnpackedBuf - */ -int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); - -/*! \brief Decodes a NFAPI P5 message - * \param pMessageBuf A pointer to an encoded P5 message - * \param messageBufLen The size of the encoded P5 message - * \param pUnpackedBuf A pointer to the nfapi_message_header - * \param unpackedBufLen The size of nfapi_message_header structure. - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf - */ -int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); - -/*! \brief Encodes an NFAPI P7 message to a buffer - * \param pMessageBuf A pointer to a nfapi p7 message structure - * \param pPackedBuf A pointer to the buffer that the p7 message will be packed into - * \param packedBufLen The size of the buffer - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will encode a nFAPI P7 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf. - * - */ -int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); - -/*! \brief Decodes an NFAPI P7 message header - * \param pMessageBuf A pointer to an encoded P7 message header - * \param messageBufLen The size of the encoded P7 message header - * \param pUnpackedBuf A pointer to the nfapi_message_header - * \param unpackedBufLen The size of nfapi_message_header structure. - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p7_message_header structure pointer to by pUnpackedBuf - - */ -int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); - -/*! \brief Decodes a NFAPI P7 message - * \param pMessageBuf A pointer to an encoded P7 message - * \param messageBufLen The size of the encoded P7 message - * \param pUnpackedBuf A pointer to the nfapi_message_header - * \param unpackedBufLen The size of nfapi_message_header structure. - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf - */ -int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); - -/*! \brief Calculates the checksum of a message - * - * \param buffer Pointer to the packed message - * \param len The length of the message - * \return The checksum. If there is an error the function with return -1 - */ -uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len); - -/*! \brief Calculates & updates the checksum in the message - * - * \param buffer Pointer to the packed message - * \param len The length of the message - * \return 0 means success, -1 means failure. - */ -int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len); - -/*! \brief Updates the transmition time stamp in the p7 message header - * - * \param buffer Pointer to the packed message - * \param timestamp The time stamp value - * \return 0 means success, -1 means failure. - */ -int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp); - -#endif /* _NFAPI_INTERFACE_H_ */ diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 91b318f94e356f163c11745b5fa75c5f17a3621b..1d393af8d6bbdf3f93e09a5744c30d64609b6d2c 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -33,6 +33,7 @@ #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "PHY/LTE_REFSIG/lte_refsig.h" +#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" //uint8_t dmrs1_tab_ue[8] = {0,2,3,4,6,8,9,10}; @@ -841,17 +842,17 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, pbch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); pbch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pbch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pbch_vars[eNB_id]->llr = (int8_t*)malloc16_clear( 1920 ); + pbch_vars[eNB_id]->llr = (int8_t*)malloc16_clear( 1920 );// prach_vars[eNB_id]->prachF = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); prach_vars[eNB_id]->prach = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); for (i=0; i<fp->nb_antennas_rx; i++) { - pbch_vars[eNB_id]->rxdataF_ext[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); + pbch_vars[eNB_id]->rxdataF_ext[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*20*12*4 ); for (j=0; j<4; j++) {//fp->nb_antennas_tx;j++) { int idx = (j<<1)+i; - pbch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); - pbch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); + pbch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*20*12*4 ); + pbch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*20*12*4 ); } } } @@ -955,6 +956,9 @@ void phy_init_nr_top(NR_DL_FRAME_PARMS *frame_parms) generate_ul_reference_signal_sequences(SHRT_MAX); + // Polar encoder init for PBCH + nr_polar_init(&frame_parms->pbch_polar_params, 1); + //lte_sync_time_init(frame_parms); //generate_ul_ref_sigs(); diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 1fcaaed494362ce17fcacf5bb354c0c437d3fd71..8512beb0d521801dfa200ac756f6c5832a5c5883 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -165,18 +165,6 @@ int nr_init_frame_parms_ue(nfapi_config_request_t* config, LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",mu, N_RB, Ncp); #endif - frame_parms->frame_type = FDD; - frame_parms->tdd_config = 3; - //frame_parms[CC_id]->tdd_config_S = 0; - frame_parms->N_RB_DL = 100; - frame_parms->N_RB_UL = 100; - frame_parms->Ncp = NORMAL; - //frame_parms[CC_id]->Ncp_UL = NORMAL; - frame_parms->Nid_cell = 0; - //frame_parms[CC_id]->num_MBSFN_config = 0; - frame_parms->nb_antenna_ports_eNB = 1; - frame_parms->nb_antennas_tx = 1; - frame_parms->nb_antennas_rx = 1; if (Ncp == EXTENDED) AssertFatal(mu == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n", Ncp, mu); diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 0b3ffe5bc7bc0b8c67be1d2763af54e8f18c83b0..f9b4afeb34334e958d074c7d13e7af25d554c13e 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -49,7 +49,9 @@ int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}}; int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1},{1,1},{1,-1},{1,1},{1,1}}; int wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}}; -short nr_mod_table[14] = {0,0,23170,23170,-23170,-23170,23170,23170,23170,-23170,-23170,23170,-23170,-23170}; +//short nr_mod_table[14] = {0,0,-23170,-23170,23170,23170,-23170,-23170,-23170,23170,23170,-23170,23170,23170}; + short nr_mod_table[14] = {0,0,23170,-23170,-23170,23170,23170,-23170,23170,23170,-23170,-23170,-23170,23170}; +//short nr_mod_table[14] = {0,0,23170,23170,-23170,-23170,23170,23170,23170,-23170,-23170,23170,-23170,-23170}; //extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; @@ -149,8 +151,8 @@ int nr_pbch_dmrs_rx(unsigned int *nr_gold_pbch, ((int16_t*)output)[(m<<1)+1] = nr_mod_table[((1 + ((nr_gold_pbch[m>>5]&(1<<(m&0x1f)))>>(m&0x1f)))<<1) + 1]; #ifdef DEBUG_PBCH //printf("nr_gold_pbch[m>>5] %x\n",nr_gold_pbch[m>>5]); - if (m<6) - printf("m %d output %d %d addr %p\n", m, output[2*m], output[2*m+1],&output[0]); + if (m<16) + printf("m %d output %d %d addr %p\n", m, ((int16_t*)output)[m<<1], ((int16_t*)output)[(m<<1)+1],&output[0]); #endif } diff --git a/openair1/PHY/NR_TRANSPORT/nr_mcs.c b/openair1/PHY/NR_TRANSPORT/nr_mcs.c new file mode 100644 index 0000000000000000000000000000000000000000..979a576256e8b37048f47aa65673c989d1e0883f --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_mcs.c @@ -0,0 +1,59 @@ +/* + * 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 + */ + +/*! \file PHY/NR_TRANSPORT/nr_mcs.c +* \brief Some support routines for NR MCS computations +* \author +* \date 2018 +* \version 0.1 +* \company Eurecom +* \email: +* \note +* \warning +*/ + +#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" + +//get_Qm under PHY/LTE_TRANSPORT/lte_mcs.c is the same for NR. + +uint8_t get_nr_Qm(uint8_t I_MCS) +{ + if (I_MCS < 5) + return(2); + else if (I_MCS < 11) + return(4); + else if (I_MCS < 20) + return(6); + else + return(8); +} + +uint8_t get_nr_Qm_ul(uint8_t I_MCS) { + + if (I_MCS < 2) + return(2); //This should be 1 if UE has reported to support pi/2 BPSK, and 2 otherwise. + else if (I_MCS < 10) + return(2); + else if (I_MCS < 17) + return(4); + else + return(6); +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h new file mode 100644 index 0000000000000000000000000000000000000000..b014748bca50b00ab0b74143795af18743e2fded --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h @@ -0,0 +1,46 @@ +/* + * 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 + */ + +/*! \file PHY/NR_TRANSPORT/nr_mcs.c +* \brief Some support routines for NR MCS computations +* \author +* \date 2018 +* \version 0.1 +* \company Eurecom +* \email: +* \note +* \warning +*/ + +#ifndef __NR_TRANSPORT_COMMON_PROTO__H__ +#define __NR_TRANSPORT_COMMON_PROTO__H__ + +// Functions below implement minor procedures from 38-214 + +/** \brief Computes Q based on I_MCS PDSCH and when 'MCS-Table-PDSCH' is set to "256QAM". Implements Table 5.1.3.1-2 from 38.214. + @param I_MCS */ +uint8_t get_nr_Qm(uint8_t I_MCS); + +/** \brief Computes Q based on I_MCS PUSCH. Implements Table 6.1.4.1-1 from 38.214. + @param I_MCS */ +uint8_t get_nr_Qm_ul(uint8_t I_MCS); + +#endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 2d262e845851e396e3ff1e305d7ace48f1615356..ad3f74452c0fdd7b1ffa68a169c4e301b5212d2b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -27,7 +27,7 @@ #include "PHY/defs_nr_UE.h" #include "filt16a_32.h" #include "T.h" -#define DEBUG_CH +//#define DEBUG_CH int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, uint8_t eNB_id, @@ -41,20 +41,19 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned char aarx; unsigned short k; unsigned int pilot_cnt; - int16_t ch[2],*pil,*rxF,*dl_ch,*fl,*fm,*f2l,*fr,f1,*f2r,*fl_dc,*fm_dc,*fr_dc; + int16_t ch[2],*pil,*rxF,*dl_ch,*fl,*fm,*fr; int ch_offset,symbol_offset; - uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; + //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; - uint8_t nushift; - uint8_t previous_thread_id = ue->current_thread_id[Ns>>1]==0 ? (RX_NB_TH-1):(ue->current_thread_id[Ns>>1]-1); - int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset]; + uint8_t nushift, Lmax, ssb_index=0, n_hf=0; + int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset]; int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF; - - // recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation - nushift = Nid_cell%4; - + Lmax = 8; //to be updated + nushift = (Lmax < 8)? ssb_index&3 : ssb_index&7; + ue->frame_parms.nushift = nushift; + if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage ch_offset = ue->frame_parms.ofdm_symbol_size ; else @@ -74,48 +73,24 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, fl = filt16a_l0; fm = filt16a_m0; fr = filt16a_r0; - fl_dc = filt16a_l0; - fm_dc = filt16a_m0; - fr_dc = filt16a_r0; - f1 = filt16a_1; - f2l = filt16a_2l0; - f2r = filt16a_2r0; break; case 1: fl = filt16a_l1; fm = filt16a_m1; fr = filt16a_r1; - fl_dc = filt16a_l1; - fm_dc = filt16a_m1; - fr_dc = filt16a_r1; - f1 = filt16a_1; - f2l = filt16a_2l1; - f2r = filt16a_2r1; break; case 2: fl = filt16a_l2; fm = filt16a_m2; fr = filt16a_r2; - fl_dc = filt16a_l2; - fm_dc = filt16a_m2; - fr_dc = filt16a_r2; - f1 = filt16a_1; - f2l = filt16a_2l0; - f2r = filt16a_2r0; break; case 3: fl = filt16a_l3; fm = filt16a_m3; fr = filt16a_r3; - fl_dc = filt16a_l3; - fm_dc = filt16a_m3; - fr_dc = filt16a_r3; - f1 = filt16a_1; - f2l = filt16a_2l1; - f2r = filt16a_2r1; break; default: @@ -124,11 +99,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, break; } - - // generate pilot - nr_pbch_dmrs_rx(ue->nr_gold_pbch, - &pilot[p][0]); + nr_pbch_dmrs_rx(ue->nr_gold_pbch[n_hf][ssb_index], &pilot[p][0]); for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) { @@ -154,7 +126,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_CH printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); - printf("pilot 0 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fl, ch, @@ -162,8 +134,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, 16); pil+=2; rxF+=8; - for (int i= 0; i<8; i++) - printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); + //for (int i= 0; i<8; i++) + //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); 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); @@ -174,19 +146,15 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - //printf("after dl_ch %d %d\n", dl_ch, *(dl_ch)); - //for (int i= 0; i<16; i++) - // printf("dl_ch %d %d\n", dl_ch+i, *(dl_ch+i)); - pil+=2; rxF+=8; 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); - #ifdef DEBUG_CH - printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - #endif +#ifdef DEBUG_CH + printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif multadd_real_vector_complex_scalar(fr, ch, @@ -204,7 +172,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, 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); #ifdef DEBUG_CH - //printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fl, ch, @@ -220,7 +188,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, 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); #ifdef DEBUG_CH - //printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fm, ch, @@ -232,9 +200,9 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, 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); - #ifdef DEBUG_CH - // printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - #endif +#ifdef DEBUG_CH + printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif multadd_real_vector_complex_scalar(fr, ch, @@ -249,8 +217,6 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, } - printf("finish dl_ch addr %p\n", dl_ch); - } return(0); diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c new file mode 100755 index 0000000000000000000000000000000000000000..fd079b9f7bd74a7ee4850a6ffd7002c29c1ac01b --- /dev/null +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -0,0 +1,6438 @@ +/* + * 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 + */ + +/*! \file PHY/LTE_TRANSPORT/dci_nr.c + * \brief Implements PDCCH physical channel TX/RX procedures (36.211) and DCI encoding/decoding (36.212/36.213). Current LTE compliance V8.6 2009-03. + * \author R. Knopp, A. Mico Pereperez + * \date 2018 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr + * \note + * \warning + */ +#ifdef USER_MODE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#endif +//#include "PHY/defs.h" +#include "PHY/defs_nr_UE.h" +//#include "PHY/extern.h" +//#include "SCHED/defs.h" +//#include "SIMULATION/TOOLS/defs.h" // for taus +#include "PHY/sse_intrin.h" + +#include "assertions.h" +#include "T.h" + +//#define DEBUG_DCI_ENCODING 1 +//#define DEBUG_DCI_DECODING 1 +//#define DEBUG_PHY + +//#define NR_LTE_PDCCH_DCI_SWITCH +#define NR_PDCCH_DCI_RUN // activates new nr functions +#define NR_PDCCH_DCI_DEBUG // activates NR_PDCCH_DCI_DEBUG logs +#define NR_NBR_CORESET_ACT_BWP 3 // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0) +#define NR_NBR_SEARCHSPACE_ACT_BWP 10 // The number of SearSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0) + +//#undef ALL_AGGREGATION + +//extern uint16_t phich_reg[MAX_NUM_PHICH_GROUPS][3]; +//extern uint16_t pcfich_reg[4]; + +/*uint32_t check_phich_reg(NR_DL_FRAME_PARMS *frame_parms,uint32_t kprime,uint8_t lprime,uint8_t mi) +{ + + uint16_t i; + uint16_t Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48; + uint16_t mprime; + uint16_t *pcfich_reg = frame_parms->pcfich_reg; + + if ((lprime>0) && (frame_parms->Ncp==0) ) + return(0); + + // printf("check_phich_reg : mi %d\n",mi); + + // compute REG based on symbol + if ((lprime == 0)|| + ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4))) + mprime = kprime/6; + else + mprime = kprime>>2; + + // check if PCFICH uses mprime + if ((lprime==0) && + ((mprime == pcfich_reg[0]) || + (mprime == pcfich_reg[1]) || + (mprime == pcfich_reg[2]) || + (mprime == pcfich_reg[3]))) { +#ifdef DEBUG_DCI_ENCODING + printf("[PHY] REG %d allocated to PCFICH\n",mprime); +#endif + return(1); + } + + // handle Special subframe case for TDD !!! + + // printf("Checking phich_reg %d\n",mprime); + if (mi > 0) { + if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0) + Ngroup_PHICH++; + + if (frame_parms->Ncp == 1) { + Ngroup_PHICH<<=1; + } + + + + for (i=0; i<Ngroup_PHICH; i++) { + if ((mprime == frame_parms->phich_reg[i][0]) || + (mprime == frame_parms->phich_reg[i][1]) || + (mprime == frame_parms->phich_reg[i][2])) { +#ifdef DEBUG_DCI_ENCODING + printf("[PHY] REG %d (lprime %d) allocated to PHICH\n",mprime,lprime); +#endif + return(1); + } + } + } + + return(0); +}*/ + +uint16_t extract_crc(uint8_t *dci,uint8_t dci_len) +{ + + uint16_t crc16; + // uint8_t i; + + /* + uint8_t crc; + crc = ((uint16_t *)dci)[DCI_LENGTH>>4]; + printf("crc1: %x, shift %d (DCI_LENGTH %d)\n",crc,DCI_LENGTH&0xf,DCI_LENGTH); + crc = (crc>>(DCI_LENGTH&0xf)); + // clear crc bits + ((uint16_t *)dci)[DCI_LENGTH>>4] &= (0xffff>>(16-(DCI_LENGTH&0xf))); + printf("crc2: %x, dci0 %x\n",crc,((int16_t *)dci)[DCI_LENGTH>>4]); + crc |= (((uint16_t *)dci)[1+(DCI_LENGTH>>4)])<<(16-(DCI_LENGTH&0xf)); + // clear crc bits + (((uint16_t *)dci)[1+(DCI_LENGTH>>4)]) = 0; + printf("extract_crc: crc %x\n",crc); + */ +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY,"dci_crc (%x,%x,%x), dci_len&0x7=%d\n",dci[dci_len>>3],dci[1+(dci_len>>3)],dci[2+(dci_len>>3)], + dci_len&0x7); +#endif + + if ((dci_len&0x7) > 0) { + ((uint8_t *)&crc16)[0] = dci[1+(dci_len>>3)]<<(dci_len&0x7) | dci[2+(dci_len>>3)]>>(8-(dci_len&0x7)); + ((uint8_t *)&crc16)[1] = dci[(dci_len>>3)]<<(dci_len&0x7) | dci[1+(dci_len>>3)]>>(8-(dci_len&0x7)); + } else { + ((uint8_t *)&crc16)[0] = dci[1+(dci_len>>3)]; + ((uint8_t *)&crc16)[1] = dci[(dci_len>>3)]; + } + +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY,"dci_crc =>%x\n",crc16); +#endif + + // dci[(dci_len>>3)]&=(0xffff<<(dci_len&0xf)); + // dci[(dci_len>>3)+1] = 0; + // dci[(dci_len>>3)+2] = 0; + return((uint16_t)crc16); + +} + + + +static uint8_t d[3*(MAX_DCI_SIZE_BITS + 16) + 96]; +static uint8_t w[3*3*(MAX_DCI_SIZE_BITS+16)]; + +void dci_encoding(uint8_t *a, + uint8_t A, + uint16_t E, + uint8_t *e, + uint16_t rnti) +{ + + + uint8_t D = (A + 16); + uint32_t RCC; + +#ifdef DEBUG_DCI_ENCODING + int32_t i; +#endif + // encode dci + +#ifdef DEBUG_DCI_ENCODING + printf("Doing DCI encoding for %d bits, e %p, rnti %x\n",A,e,rnti); +#endif + + memset((void *)d,LTE_NULL,96); + + ccodelte_encode(A,2,a,d+96,rnti); + +#ifdef DEBUG_DCI_ENCODING + + for (i=0; i<16+A; i++) + printf("%d : (%d,%d,%d)\n",i,*(d+96+(3*i)),*(d+97+(3*i)),*(d+98+(3*i))); + +#endif + +#ifdef DEBUG_DCI_ENCODING + printf("Doing DCI interleaving for %d coded bits, e %p\n",D*3,e); +#endif + RCC = sub_block_interleaving_cc(D,d+96,w); + +#ifdef DEBUG_DCI_ENCODING + printf("Doing DCI rate matching for %d channel bits, RCC %d, e %p\n",E,RCC,e); +#endif + lte_rate_matching_cc(RCC,E,w,e); + + +} + + +uint8_t *generate_dci0(uint8_t *dci, + uint8_t *e, + uint8_t DCI_LENGTH, + uint8_t aggregation_level, + uint16_t rnti) +{ + + uint16_t coded_bits; + uint8_t dci_flip[8]; + + if (aggregation_level>3) { + printf("dci.c: generate_dci FATAL, illegal aggregation_level %d\n",aggregation_level); + return NULL; + } + + coded_bits = 72 * (1<<aggregation_level); + + /* + + #ifdef DEBUG_DCI_ENCODING + for (i=0;i<1+((DCI_LENGTH+16)/8);i++) + printf("i %d : %x\n",i,dci[i]); + #endif + */ + if (DCI_LENGTH<=32) { + dci_flip[0] = dci[3]; + dci_flip[1] = dci[2]; + dci_flip[2] = dci[1]; + dci_flip[3] = dci[0]; + } else { + dci_flip[0] = dci[7]; + dci_flip[1] = dci[6]; + dci_flip[2] = dci[5]; + dci_flip[3] = dci[4]; + dci_flip[4] = dci[3]; + dci_flip[5] = dci[2]; + dci_flip[6] = dci[1]; + dci_flip[7] = dci[0]; +#ifdef DEBUG_DCI_ENCODING + printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n", + dci_flip[0],dci_flip[1],dci_flip[2],dci_flip[3], + dci_flip[4],dci_flip[5],dci_flip[6],dci_flip[7]); +#endif + } + + dci_encoding(dci_flip,DCI_LENGTH,coded_bits,e,rnti); + + return(e+coded_bits); +} + +uint32_t Y; + +#define CCEBITS 72 +#define CCEPERSYMBOL 33 // This is for 1200 RE +#define CCEPERSYMBOL0 22 // This is for 1200 RE +#define DCI_BITS_MAX ((2*CCEPERSYMBOL+CCEPERSYMBOL0)*CCEBITS) +#define Msymb (DCI_BITS_MAX/2) +//#define Mquad (Msymb/4) + +static uint32_t bitrev_cc_dci[32] = {1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31,0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30}; +static int32_t wtemp[2][Msymb]; + +void pdcch_interleaving(NR_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **wbar,uint8_t n_symbols_pdcch,uint8_t mi) +{ + + int32_t *wptr,*wptr2,*zptr; + uint32_t Mquad = get_nquad(n_symbols_pdcch,frame_parms,mi); + uint32_t RCC = (Mquad>>5), ND; + uint32_t row,col,Kpi,index; + int32_t i,k,a; +#ifdef RM_DEBUG + int32_t nulled=0; +#endif + + // printf("[PHY] PDCCH Interleaving Mquad %d (Nsymb %d)\n",Mquad,n_symbols_pdcch); + if ((Mquad&0x1f) > 0) + RCC++; + + Kpi = (RCC<<5); + ND = Kpi - Mquad; + + k=0; + + for (col=0; col<32; col++) { + index = bitrev_cc_dci[col]; + + for (row=0; row<RCC; row++) { + //printf("col %d, index %d, row %d\n",col,index,row); + if (index>=ND) { + for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) { + //printf("a %d k %d\n",a,k); + + wptr = &wtemp[a][k<<2]; + zptr = &z[a][(index-ND)<<2]; + + //printf("wptr=%p, zptr=%p\n",wptr,zptr); + + wptr[0] = zptr[0]; + wptr[1] = zptr[1]; + wptr[2] = zptr[2]; + wptr[3] = zptr[3]; + } + + k++; + } + + index+=32; + } + } + + // permutation + for (i=0; i<Mquad; i++) { + + for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) { + + //wptr = &wtemp[a][i<<2]; + //wptr2 = &wbar[a][((i+frame_parms->Nid_cell)%Mquad)<<2]; + wptr = &wtemp[a][((i+frame_parms->Nid_cell)%Mquad)<<2]; + wptr2 = &wbar[a][i<<2]; + wptr2[0] = wptr[0]; + wptr2[1] = wptr[1]; + wptr2[2] = wptr[2]; + wptr2[3] = wptr[3]; + } + } +} + + + +#ifdef NR_PDCCH_DCI_RUN +void nr_pdcch_demapping(uint16_t *llr, uint16_t *wbar, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t coreset_time_dur, uint32_t coreset_nbr_rb) { +/* + * LLR contains the PDCCH for the coreset_time_dur symbols in the following sequence: + * + * The REGs have to be numbered in increasing order in a time-first manner, + * starting with 0 for the first OFDM symbol and the lowest-numbered resource + * block in the control resource set + * + * | ... | ... | ... | + * | REG 3 | REG 4 | REG 5 | + * | REG 0 | REG 1 | REG 2 | + * | symbol0 | symbol1 | symbol2 | + * + * ................. + * ___________REG 1+2l + * ___________REG 1+l + * symbol 1___REG 1 + * ................. + * ___________REG 2l + * ___________REG l + * symbol 0___REG 0 + * + * WBAR will contain the PDCCH organized in REGx where x will be consecutive: + * REG 0 + * REG 1 + * REG 2 + * ... + * REG l + * REG 1+l + * REG 2+l + * ... + * + */ + + uint32_t m,i,k,l; + uint32_t num_re_pdcch = 12 * coreset_nbr_rb; + i=0; + m=0; + for (k=0; k<num_re_pdcch; k++) { + for (l=0; l < coreset_time_dur ; l++) { + if ((k%12==1)||(k%12==5)||(k%12==9)){ + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping)-> k,l=(%d,%d) DM-RS PDCCH signal\n",k,l); + #endif + } else { + if ((m%9)==0 && (m !=0) && (l==0)) { + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping)-> we have modified m: old_m=%d, new_m=%d\n", + m,m+(9*(coreset_time_dur-1))); + #endif + m=m+(9*(coreset_time_dur-1)); // to avoid overwriting m+1 when a whole REG has been completed + } + wbar[(l*9)+m] = llr[(l*9*coreset_nbr_rb)+i]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping)-> k,l=(%d,%d) i,m=(%d,%d) REG (%d) > wbar(%d,%d) \t llr[%d]->wbar[%d]\n", + k,l,i,m, (m+(l*9)) / 9, *(char*) &wbar[m+(l*9)], *(1 + (char*) &wbar[m+(l*9)]), + (l*9*coreset_nbr_rb)+i,m+(l*9)); + #endif + if (l==coreset_time_dur-1) { + i++; + m++; + } + } + } + } +} +#endif + + +void pdcch_demapping(uint16_t *llr,uint16_t *wbar,NR_DL_FRAME_PARMS *frame_parms,uint8_t num_pdcch_symbols,uint8_t mi) +{ + + uint32_t i, lprime; + uint16_t kprime,kprime_mod12,mprime,symbol_offset,tti_offset,tti_offset0; + int16_t re_offset,re_offset0; + + // This is the REG allocation algorithm from 36-211, second part of Section 6.8.5 + + int Msymb2; + + switch (frame_parms->N_RB_DL) { + case 100: + Msymb2 = Msymb; + break; + + case 75: + Msymb2 = 3*Msymb/4; + break; + + case 50: + Msymb2 = Msymb>>1; + break; + + case 25: + Msymb2 = Msymb>>2; + break; + + case 15: + Msymb2 = Msymb*15/100; + break; + + case 6: + Msymb2 = Msymb*6/100; + break; + + default: + Msymb2 = Msymb>>2; + break; + } + + mprime=0; + + + re_offset = 0; + re_offset0 = 0; // counter for symbol with pilots (extracted outside!) + + for (kprime=0; kprime<frame_parms->N_RB_DL*12; kprime++) { + for (lprime=0; lprime<num_pdcch_symbols; lprime++) { + + symbol_offset = (uint32_t)frame_parms->N_RB_DL*12*lprime; + + tti_offset = symbol_offset + re_offset; + tti_offset0 = symbol_offset + re_offset0; + + // if REG is allocated to PHICH, skip it + if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) { + // printf("dci_demapping : skipping REG %d (RE %d)\n",(lprime==0)?kprime/6 : kprime>>2,kprime); + if ((lprime == 0)&&((kprime%6)==0)) + re_offset0+=4; + } else { // not allocated to PHICH/PCFICH + // printf("dci_demapping: REG %d\n",(lprime==0)?kprime/6 : kprime>>2); + if (lprime == 0) { + // first symbol, or second symbol+4 TX antennas skip pilots + kprime_mod12 = kprime%12; + + if ((kprime_mod12 == 0) || (kprime_mod12 == 6)) { + // kprime represents REG + + for (i=0; i<4; i++) { + wbar[mprime] = llr[tti_offset0+i]; +#ifdef DEBUG_DCI_DECODING +// LOG_I(PHY,"PDCCH demapping mprime %d.%d <= llr %d (symbol %d re %d) -> (%d,%d)\n",mprime/4,i,tti_offset0+i,symbol_offset,re_offset0,*(char*)&wbar[mprime],*(1+(char*)&wbar[mprime])); +#endif + mprime++; + re_offset0++; + } + } + } else if ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)) { + // LATER!!!! + } else { // no pilots in this symbol + kprime_mod12 = kprime%12; + + if ((kprime_mod12 == 0) || (kprime_mod12 == 4) || (kprime_mod12 == 8)) { + // kprime represents REG + for (i=0; i<4; i++) { + wbar[mprime] = llr[tti_offset+i]; +#ifdef DEBUG_DCI_DECODING +// LOG_I(PHY,"PDCCH demapping mprime %d.%d <= llr %d (symbol %d re %d) -> (%d,%d)\n",mprime/4,i,tti_offset+i,symbol_offset,re_offset+i,*(char*)&wbar[mprime],*(1+(char*)&wbar[mprime])); +#endif + mprime++; + } + } // is representative + } // no pilots case + } // not allocated to PHICH/PCFICH + + // Stop when all REGs are copied in + if (mprime>=Msymb2) + break; + } //lprime loop + + re_offset++; + + } // kprime loop +} + +static uint16_t wtemp_rx[Msymb]; + + +#ifdef NR_PDCCH_DCI_RUN +void nr_pdcch_deinterleaving(NR_DL_FRAME_PARMS *frame_parms, uint16_t *z, + uint16_t *wbar, uint8_t coreset_time_dur, uint8_t reg_bundle_size_L, + uint8_t coreset_interleaver_size_R, uint8_t n_shift, uint32_t coreset_nbr_rb) +{ +/* + * This function will perform deinterleaving described in 38.211 Section 7.3.2.2 + * coreset_freq_dom (bit map 45 bits: each bit indicates 6 RB in CORESET -> 1 bit MSB indicates PRB 0..6 are part of CORESET) + * coreset_time_dur (1,2,3) + * coreset_CCE_REG_mapping_type (interleaved, non-interleaved) + * reg_bundle_size (2,3,6) + */ +#ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_deinterleaving)-> coreset_nbr_rb=(%lld), reg_bundle_size_L=(%d)\n", + coreset_nbr_rb,reg_bundle_size_L); +#endif +/* + * First verify that CORESET is interleaved or not interleaved depending on parameter cce-REG-MappingType + * To be done + * if non-interleaved then do nothing: wbar table stays as it is + * if interleaved then do this: wbar table has bundles interleaved. We have to de-interleave then + * following procedure described in 38.211 Section 7.3.2.2: + */ + int coreset_interleaved = 1; + uint32_t bundle_id, bundle_interleaved, c=0 ,r=-1, k, l, i=0; + uint32_t coreset_C = (uint32_t)(coreset_nbr_rb / (coreset_interleaver_size_R*reg_bundle_size_L)); + uint16_t *wptr; + wptr = &wtemp_rx[0]; + z = &wtemp_rx[0]; + bundle_id=0; + for (k=0 ; k<9*coreset_nbr_rb*coreset_time_dur; k++){ +#ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_deinterleaving)-> k=%d \t coreset_interleaved=%d reg_bundle_size_L=%d coreset_C=%d coreset_interleaver_R=%d", + k,coreset_interleaved,reg_bundle_size_L, coreset_C,coreset_interleaver_size_R); +#endif + if (k%(9*reg_bundle_size_L)==0) { + // calculate offset properly + if (r==coreset_interleaver_size_R-1) { + //if (bundle_id>=(c+1)*coreset_interleaver_size_R) { + c++; + r=0; + } else{ + r++; + } +#ifdef NR_PDCCH_DCI_DEBUG + printf("\t --> time to modify bundle_interleaved and bundle_id --> r=%d c=%d",r,c); +#endif + bundle_id=c*coreset_interleaver_size_R+r; + bundle_interleaved=(r*coreset_C+c+n_shift)%(coreset_nbr_rb * coreset_time_dur/reg_bundle_size_L); + } + if (coreset_interleaved == 1){ + //wptr[i+(bundle_interleaved-bundle_id)*9*reg_bundle_size_L]=wbar[i]; +#ifdef NR_PDCCH_DCI_DEBUG + printf("\n\t\t\t\t\t\t\t\t\t wptr[%d] <-> wbar[%d]",i,i+(bundle_interleaved-bundle_id)*9*reg_bundle_size_L); +#endif + wptr[i]=wbar[i+(bundle_interleaved-bundle_id)*9*reg_bundle_size_L]; +#ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t bundle_id = %d \t bundle_interleaved = %d\n",bundle_id,bundle_interleaved); +#endif + i++; + } else { + wptr[i]=wbar[i]; + i++; + } + //bundle_id=c*coreset_interleaver_size_R+r; + } +} +#endif + + + + + + + +void pdcch_deinterleaving(NR_DL_FRAME_PARMS *frame_parms,uint16_t *z, uint16_t *wbar,uint8_t number_pdcch_symbols,uint8_t mi) +{ + + uint16_t *wptr,*zptr,*wptr2; + + uint16_t Mquad=get_nquad(number_pdcch_symbols,frame_parms,mi); + uint32_t RCC = (Mquad>>5), ND; + uint32_t row,col,Kpi,index; + int32_t i,k; + + + // printf("Mquad %d, RCC %d\n",Mquad,RCC); + + if (!z) { + printf("dci.c: pdcch_deinterleaving: FATAL z is Null\n"); + return; + } + + // undo permutation + for (i=0; i<Mquad; i++) { + wptr = &wtemp_rx[((i+frame_parms->Nid_cell)%Mquad)<<2]; + wptr2 = &wbar[i<<2]; + + wptr[0] = wptr2[0]; + wptr[1] = wptr2[1]; + wptr[2] = wptr2[2]; + wptr[3] = wptr2[3]; + /* + printf("pdcch_deinterleaving (%p,%p): quad %d (%d) -> (%d,%d %d,%d %d,%d %d,%d)\n",wptr,wptr2,i,(i+frame_parms->Nid_cell)%Mquad, + ((char*)wptr2)[0], + ((char*)wptr2)[1], + ((char*)wptr2)[2], + ((char*)wptr2)[3], + ((char*)wptr2)[4], + ((char*)wptr2)[5], + ((char*)wptr2)[6], + ((char*)wptr2)[7]); + */ + + } + + if ((Mquad&0x1f) > 0) + RCC++; + + Kpi = (RCC<<5); + ND = Kpi - Mquad; + + k=0; + + for (col=0; col<32; col++) { + index = bitrev_cc_dci[col]; + + for (row=0; row<RCC; row++) { + // printf("row %d, index %d, Nd %d\n",row,index,ND); + if (index>=ND) { + + + + wptr = &wtemp_rx[k<<2]; + zptr = &z[(index-ND)<<2]; + + zptr[0] = wptr[0]; + zptr[1] = wptr[1]; + zptr[2] = wptr[2]; + zptr[3] = wptr[3]; + + /* + printf("deinterleaving ; k %d, index-Nd %d => (%d,%d,%d,%d,%d,%d,%d,%d)\n",k,(index-ND), + ((int8_t *)wptr)[0], + ((int8_t *)wptr)[1], + ((int8_t *)wptr)[2], + ((int8_t *)wptr)[3], + ((int8_t *)wptr)[4], + ((int8_t *)wptr)[5], + ((int8_t *)wptr)[6], + ((int8_t *)wptr)[7]); + */ + k++; + } + + index+=32; + + } + } + + for (i=0; i<Mquad; i++) { + zptr = &z[i<<2]; + /* + printf("deinterleaving ; quad %d => (%d,%d,%d,%d,%d,%d,%d,%d)\n",i, + ((int8_t *)zptr)[0], + ((int8_t *)zptr)[1], + ((int8_t *)zptr)[2], + ((int8_t *)zptr)[3], + ((int8_t *)zptr)[4], + ((int8_t *)zptr)[5], + ((int8_t *)zptr)[6], + ((int8_t *)zptr)[7]); + */ + } + +} + + +int32_t pdcch_qpsk_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int32_t **rxdataF_comp_i, + int32_t **rho_i, + int16_t *pdcch_llr16, + int16_t *pdcch_llr8in, + uint8_t symbol) +{ + + int16_t *rxF=(int16_t*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; + int16_t *rxF_i=(int16_t*)&rxdataF_comp_i[0][(symbol*frame_parms->N_RB_DL*12)]; + int16_t *rho=(int16_t*)&rho_i[0][(symbol*frame_parms->N_RB_DL*12)]; + int16_t *llr128; + int32_t i; + char *pdcch_llr8; + int16_t *pdcch_llr; + pdcch_llr8 = (char *)&pdcch_llr8in[symbol*frame_parms->N_RB_DL*12]; + pdcch_llr = &pdcch_llr16[symbol*frame_parms->N_RB_DL*12]; + + // printf("dlsch_qpsk_qpsk: symbol %d\n",symbol); + + llr128 = (int16_t*)pdcch_llr; + + if (!llr128) { + printf("dlsch_qpsk_qpsk_llr: llr is null, symbol %d\n",symbol); + return -1; + } + + qpsk_qpsk(rxF, + rxF_i, + llr128, + rho, + frame_parms->N_RB_DL*12); + + //prepare for Viterbi which accepts 8 bit, but prefers 4 bit, soft input. + for (i=0; i<(frame_parms->N_RB_DL*24); i++) { + if (*pdcch_llr>7) + *pdcch_llr8=7; + else if (*pdcch_llr<-8) + *pdcch_llr8=-8; + else + *pdcch_llr8 = (char)(*pdcch_llr); + + pdcch_llr++; + pdcch_llr8++; + } + + return(0); +} + + +#ifdef NR_PDCCH_DCI_RUN +int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, + char *pdcch_llr, uint8_t symbol,uint32_t coreset_nbr_rb) { + + int16_t *rxF = (int16_t*) &rxdataF_comp[0][(symbol * frame_parms->N_RB_DL * 12)]; + int32_t i; + char *pdcch_llr8; + + pdcch_llr8 = &pdcch_llr[2 * symbol * frame_parms->N_RB_DL * 12]; + + if (!pdcch_llr8) { + printf("pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); + return (-1); + } +#ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_llr)-> llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llr8-pdcch_llr); +#endif + //for (i = 0; i < (frame_parms->N_RB_DL * ((symbol == 0) ? 16 : 24)); i++) { + for (i = 0; i < (coreset_nbr_rb * ((symbol == 0) ? 18 : 18)); i++) { + + if (*rxF > 31) + *pdcch_llr8 = 31; + else if (*rxF < -32) + *pdcch_llr8 = -32; + else + *pdcch_llr8 = (char) (*rxF); +#ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_llr)-> llr logs: i=%d *rxF:%d => *pdcch_llr8:%d\n",i/18,i,*rxF,*pdcch_llr8); +#endif + rxF++; + pdcch_llr8++; + } + + return (0); + +} +#endif + + + +int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + char *pdcch_llr, + uint8_t symbol) +{ + + int16_t *rxF= (int16_t*) &rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; + int32_t i; + char *pdcch_llr8; + + pdcch_llr8 = &pdcch_llr[2*symbol*frame_parms->N_RB_DL*12]; + + if (!pdcch_llr8) { + printf("pdcch_qpsk_llr: llr is null, symbol %d\n",symbol); + return(-1); + } + + // printf("pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llr8-pdcch_llr); + + for (i=0; i<(frame_parms->N_RB_DL*((symbol==0) ? 16 : 24)); i++) { + + if (*rxF>31) + *pdcch_llr8=31; + else if (*rxF<-32) + *pdcch_llr8=-32; + else + *pdcch_llr8 = (char)(*rxF); + + // printf("%d %d => %d\n",i,*rxF,*pdcch_llr8); + rxF++; + pdcch_llr8++; + } + + return(0); + +} + +//__m128i avg128P; + +//compute average channel_level on each (TX,RX) antenna pair +void pdcch_channel_level(int32_t **dl_ch_estimates_ext, + NR_DL_FRAME_PARMS *frame_parms, + int32_t *avg, + uint8_t nb_rb) +{ + + int16_t rb; + uint8_t aatx,aarx; +#if defined(__x86_64__) || defined(__i386__) + __m128i *dl_ch128; + __m128i avg128P; +#elif defined(__arm__) + int16x8_t *dl_ch128; + int32x4_t *avg128P; +#endif + for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + //clear average level +#if defined(__x86_64__) || defined(__i386__) + avg128P = _mm_setzero_si128(); + dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][0]; +#elif defined(__arm__) + +#endif + for (rb=0; rb<nb_rb; rb++) { + +#if defined(__x86_64__) || defined(__i386__) + avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[0],dl_ch128[0])); + avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[1],dl_ch128[1])); + avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[2],dl_ch128[2])); +#elif defined(__arm__) + +#endif + dl_ch128+=3; + /* + if (rb==0) { + print_shorts("dl_ch128",&dl_ch128[0]); + print_shorts("dl_ch128",&dl_ch128[1]); + print_shorts("dl_ch128",&dl_ch128[2]); + } + */ + } + + DevAssert( nb_rb ); + avg[(aatx<<1)+aarx] = (((int32_t*)&avg128P)[0] + + ((int32_t*)&avg128P)[1] + + ((int32_t*)&avg128P)[2] + + ((int32_t*)&avg128P)[3])/(nb_rb*12); + + // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif + +} + +#if defined(__x86_64) || defined(__i386__) +__m128i mmtmpPD0,mmtmpPD1,mmtmpPD2,mmtmpPD3; +#elif defined(__arm__) + +#endif +/* +void pdcch_dual_stream_correlation(NR_DL_FRAME_PARMS *frame_parms, + uint8_t symbol, + int32_t **dl_ch_estimates_ext, + int32_t **dl_ch_estimates_ext_i, + int32_t **dl_ch_rho_ext, + uint8_t output_shift) +{ + + uint16_t rb; +#if defined(__x86_64__) || defined(__i386__) + __m128i *dl_ch128,*dl_ch128i,*dl_ch_rho128; +#elif defined(__arm__) + +#endif + uint8_t aarx; + + // printf("dlsch_dual_stream_correlation: symbol %d\n",symbol); + + + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + +#if defined(__x86_64__) || defined(__i386__) + dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; + dl_ch128i = (__m128i *)&dl_ch_estimates_ext_i[aarx][symbol*frame_parms->N_RB_DL*12]; + dl_ch_rho128 = (__m128i *)&dl_ch_rho_ext[aarx][symbol*frame_parms->N_RB_DL*12]; + +#elif defined(__arm__) + +#endif + + for (rb=0; rb<frame_parms->N_RB_DL; rb++) { + // multiply by conjugated channel +#if defined(__x86_64__) || defined(__i386__) + mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128i[0]); + // print_ints("re",&mmtmpPD0); + + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); + // print_ints("im",&mmtmpPD1); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[0]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + // print_ints("re(shift)",&mmtmpPD0); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + // print_ints("im(shift)",&mmtmpPD1); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + // print_ints("c0",&mmtmpPD2); + // print_ints("c1",&mmtmpPD3); + dl_ch_rho128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); + + //print_shorts("rx:",dl_ch128_2); + //print_shorts("ch:",dl_ch128); + //print_shorts("pack:",rho128); + + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128i[1]); + // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[1]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + + + dl_ch_rho128[1] =_mm_packs_epi32(mmtmpPD2,mmtmpPD3); + //print_shorts("rx:",dl_ch128_2+1); + //print_shorts("ch:",dl_ch128+1); + //print_shorts("pack:",rho128+1); + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128i[2]); + // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[2]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + + dl_ch_rho128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); + //print_shorts("rx:",dl_ch128_2+2); + //print_shorts("ch:",dl_ch128+2); + //print_shorts("pack:",rho128+2); + + dl_ch128+=3; + dl_ch128i+=3; + dl_ch_rho128+=3; + + +#elif defined(__arm__) + +#endif + } + } +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif + +} +*/ + +void pdcch_detection_mrc_i(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int32_t **rxdataF_comp_i, + int32_t **rho, + int32_t **rho_i, + uint8_t symbol) +{ + + uint8_t aatx; + +#if defined(__x86_64__) || defined(__i386__) + __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1; +#elif defined(__arm__) + int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1; +#endif + int32_t i; + + if (frame_parms->nb_antennas_rx>1) { + for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { + //if (frame_parms->mode1_flag && (aatx>0)) break; + +#if defined(__x86_64__) || defined(__i386__) + rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; +#elif defined(__arm__) + rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; +#endif + // MRC on each re of rb on MF output + for (i=0; i<frame_parms->N_RB_DL*3; i++) { +#if defined(__x86_64__) || defined(__i386__) + rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); +#elif defined(__arm__) + rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]); +#endif + } + } + +#if defined(__x86_64__) || defined(__i386__) + rho128_0 = (__m128i *) &rho[0][symbol*frame_parms->N_RB_DL*12]; + rho128_1 = (__m128i *) &rho[1][symbol*frame_parms->N_RB_DL*12]; +#elif defined(__arm__) + rho128_0 = (int16x8_t *) &rho[0][symbol*frame_parms->N_RB_DL*12]; + rho128_1 = (int16x8_t *) &rho[1][symbol*frame_parms->N_RB_DL*12]; +#endif + for (i=0; i<frame_parms->N_RB_DL*3; i++) { +#if defined(__x86_64__) || defined(__i386__) + rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1)); +#elif defined(__arm__) + rho128_0[i] = vhaddq_s16(rho128_0[i],rho128_1[i]); +#endif + } + +#if defined(__x86_64__) || defined(__i386__) + rho128_i0 = (__m128i *) &rho_i[0][symbol*frame_parms->N_RB_DL*12]; + rho128_i1 = (__m128i *) &rho_i[1][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_i0 = (__m128i *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_i1 = (__m128i *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12]; +#elif defined(__arm__) + rho128_i0 = (int16x8_t*) &rho_i[0][symbol*frame_parms->N_RB_DL*12]; + rho128_i1 = (int16x8_t*) &rho_i[1][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_i0 = (int16x8_t *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_i1 = (int16x8_t *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12]; + +#endif + // MRC on each re of rb on MF and rho + for (i=0; i<frame_parms->N_RB_DL*3; i++) { +#if defined(__x86_64__) || defined(__i386__) + rxdataF_comp128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i0[i],1),_mm_srai_epi16(rxdataF_comp128_i1[i],1)); + rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1)); +#elif defined(__arm__) + rxdataF_comp128_i0[i] = vhaddq_s16(rxdataF_comp128_i0[i],rxdataF_comp128_i1[i]); + rho128_i0[i] = vhaddq_s16(rho128_i0[i],rho128_i1[i]); + +#endif + } + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif +} + + +#ifdef NR_PDCCH_DCI_RUN +// This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources) +void nr_pdcch_extract_rbs_single(int32_t **rxdataF, + int32_t **dl_ch_estimates, + int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + uint8_t symbol, + uint32_t high_speed_flag, + NR_DL_FRAME_PARMS *frame_parms, + uint64_t coreset_freq_dom, + uint32_t coreset_nbr_rb, + uint32_t n_BWP_start) { + +/* + * This function is demapping DM-RS PDCCH RE + * Implementing 38.211 Section 7.4.1.3.2 Mapping to physical resources + * PDCCH DM-RS signals are mapped on RE a_k_l where: + * k = 12*n + 4*kprime + 1 + * n=0,1,.. + * kprime=0,1,2 + * According to this equations, DM-RS PDCCH are mapped on k where k%12==1 || k%12==5 || k%12==9 + * + */ + // the bitmap coreset_frq_domain contains 45 bits + #define CORESET_FREQ_DOMAIN_BITMAP_SIZE 45 + // each bit is associated to 6 RBs + #define BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN 6 + #define NBR_RE_PER_RB_WITH_DMRS 12 + // after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH + #define NBR_RE_PER_RB_WITHOUT_DMRS 9 + + uint16_t c_rb, c_rb_tmp, rb, nb_rb = 0; + // this variable will be incremented by 1 each time a bit set to '0' is found in coreset_freq_dom bitmap + uint16_t offset_discontiguous=0; + uint8_t rb_count_bit,i, j, aarx, bitcnt_coreset_freq_dom=0; + int32_t *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext; + int nushiftmod3 = frame_parms->nushift % 3; + uint8_t symbol_mod; + + symbol_mod = (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol; + c_rb = n_BWP_start; // c_rb is the common resource block: RB within the BWP + #ifdef DEBUG_DCI_DECODING + LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod); + #endif + + + + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + if (high_speed_flag == 1){ + dl_ch0 = &dl_ch_estimates[aarx][5 + (symbol * (frame_parms->ofdm_symbol_size))]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0 = &dl_ch_estimates[aarx = (%d)][5 + (symbol * (frame_parms->ofdm_symbol_size (%d))) = (%d)]\n", + aarx,frame_parms->ofdm_symbol_size,5 + (symbol * (frame_parms->ofdm_symbol_size))); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> why pointer is pointing to that position (what does '5' mean)?\n"); + #endif + } else { + dl_ch0 = &dl_ch_estimates[aarx][5]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0 = &dl_ch_estimates[aarx = (%d)][5]\n",aarx); + #endif + } + + dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (frame_parms->N_RB_DL * NBR_RE_PER_RB_WITH_DMRS)]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 12) = (%d)]\n", + aarx,symbol * (frame_parms->N_RB_DL * 12)); + #endif + rxF_ext = &rxdataF_ext[aarx][symbol * (frame_parms->N_RB_DL * NBR_RE_PER_RB_WITH_DMRS)]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 12) = (%d)]\n", + aarx,symbol * (frame_parms->N_RB_DL * 12)); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> (for symbol=%d, aarx=%d), symbol_mod=%d, nushiftmod3=%d \n",symbol,aarx,symbol_mod,nushiftmod3); + #endif + +/* + * The following for loop handles treatment of PDCCH contained in table rxdataF (in frequency domain) + * In NR the PDCCH IQ symbols are contained within RBs in the CORESET defined by higher layers which is located within the BWP + * Lets consider that the first RB to be considered as part of the CORESET and part of the PDCCH is n_BWP_start + * Several cases have to be handled differently as IQ symbols are situated in different parts of rxdataF: + * 1. Number of RBs in the system bandwidth is even + * 1.1 The RB is < than the N_RB_DL/2 -> IQ symbols are in the second half of the rxdataF (from first_carrier_offset) + * 1.2 The RB is >= than the N_RB_DL/2 -> IQ symbols are in the first half of the rxdataF (from element 1) + * 2. Number of RBs in the system bandwidth is odd + * (particular case when the RB with DC as it is treated differently: it is situated in symbol borders of rxdataF) + * 2.1 The RB is <= than the N_RB_DL/2 -> IQ symbols are in the second half of the rxdataF (from first_carrier_offset) + * 2.2 The RB is > than the N_RB_DL/2+1 -> IQ symbols are in the first half of the rxdataF (from element 1 + 2nd half RB containing DC) + * 2.3 The RB is == N_RB_DL/2+1 -> IQ symbols are in the lower border of the rxdataF for first 6 IQ element and the upper border of the rxdataF for the last 6 IQ elements + * If the first RB containing PDCCH within the UE BWP and within the CORESET is higher than half of the system bandwidth (N_RB_DL), + * then the IQ symbol is going to be found at the position 1+c_rb-N_RB_DL/2 in rxdataF and + * we have to point the pointer at (1+c_rb-N_RB_DL/2) in rxdataF + */ + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> n_BWP_start=%d, coreset_nbr_rb=%d\n",n_BWP_start,coreset_nbr_rb); + #endif + + for (c_rb = n_BWP_start; c_rb < (n_BWP_start + coreset_nbr_rb + (BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN * offset_discontiguous)); c_rb++) { + //c_rb_tmp = 0; + if (((c_rb - n_BWP_start) % BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN)==0) { + bitcnt_coreset_freq_dom ++; + while ((((coreset_freq_dom & 0x1FFFFFFFFFFF) >> (CORESET_FREQ_DOMAIN_BITMAP_SIZE - bitcnt_coreset_freq_dom)) & 0x1)== 0){ // 46 -> 45 is number of bits in coreset_freq_dom + // next 6 RB are not part of the CORESET within the BWP as bit in coreset_freq_dom is set to 0 + bitcnt_coreset_freq_dom ++; + //c_rb_tmp = c_rb_tmp + 6; + c_rb = c_rb + BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN; + offset_discontiguous ++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> we entered here as coreset_freq_dom=%llx (bit %d) is 0, coreset_freq_domain is discontiguous\n",coreset_freq_dom,(46 - bitcnt_coreset_freq_dom)); + #endif + } + } + //c_rb = c_rb + c_rb_tmp; + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> c_rb=%d\n",c_rb); + #endif + // first we set initial conditions for pointer to rxdataF depending on the situation of the first RB within the CORESET (c_rb = n_BWP_start) + if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { + //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): even case + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is lower than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); + #endif + } + if ((c_rb >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { + // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) + // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF + rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))); + #endif + //rxF = &rxdataF[aarx][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol + //#ifdef NR_PDCCH_DCI_DEBUG + // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + // c_rb,aarx,(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))); + //#endif + } + if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ + //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): odd case + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is lower or equal than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); + #endif + } + if ((c_rb > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ + // number of RBs is odd and c_rb is higher than half system bandwidth + 1 + // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF just after the first IQ symbols of the RB containing DC + rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - frame_parms->N_RB_DL) - 5 + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))); + #endif + } + if ((c_rb == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ // treatment of RB containing the DC + // if odd number RBs in system bandwidth and first RB to be treated is higher than middle system bandwidth (around DC) + // we have to treat the RB in two parts: first part from i=0 to 5, the data is at the end of rxdataF (pointing at the end of the table) + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL + 1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); + #endif + /*if (symbol_mod > 300) { // this if is going to be removed as DM-RS signals are present in all symbols of PDCCH + for (i = 0; i < 6; i++) { + dl_ch0_ext[i] = dl_ch0[i]; + rxF_ext[i] = rxF[i]; + } + rxF = &rxdataF[aarx][(symbol * (frame_parms->ofdm_symbol_size))]; // we point at the 1st part of the rxdataF in symbol + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", + c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size))); + #endif + for (; i < 12; i++) { + dl_ch0_ext[i] = dl_ch0[i]; + rxF_ext[i] = rxF[(1 + i - 6)]; + } + nb_rb++; + dl_ch0_ext += 12; + rxF_ext += 12; + dl_ch0 += 12; + rxF += 7; + c_rb++; + } else {*/ + j = 0; + for (i = 0; i < 6; i++) { //treating first part of the RB note that i=5 would correspond to DC. We treat it in NR + if ((i != 1) && (i != 5)) { + dl_ch0_ext[j] = dl_ch0[i]; + rxF_ext[j++] = rxF[i]; + // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); + } + } + // then we point at the begining of the symbol part of rxdataF do process second part of RB + rxF = &rxdataF[aarx][((symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", + c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size))); + #endif + for (; i < 12; i++) { + if ((i != 9)) { + dl_ch0_ext[j] = dl_ch0[i]; + rxF_ext[j++] = rxF[(1 + i - 6)]; + // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); + } + } + nb_rb++; + dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; + rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; + dl_ch0 += 12; + //rxF += 7; + //c_rb++; + //n_BWP_start++; // We have to increment this variable here to be consequent in the for loop afterwards + //} + } else { // treatment of any RB that does not contain the DC + /*if (symbol_mod > 300) { + memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); + for (i = 0; i < 12; i++) { + rxF_ext[i] = rxF[i]; + } + nb_rb++; + dl_ch0_ext += 12; + rxF_ext += 12; + dl_ch0 += 12; + //rxF += 12; + } else {*/ + j = 0; + for (i = 0; i < 12; i++) { + if ((i != 1) && (i != 5) && (i != 9)) { + rxF_ext[j] = rxF[i]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d)", + c_rb, i, j, *(short *) &rxF_ext[j],*(1 + (short*) &rxF_ext[j]), i, + *(short *) &rxF[i], *(1 + (short*) &rxF[i])); + #endif + dl_ch0_ext[j++] = dl_ch0[i]; + //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> ch %d => dl_ch0(%d,%d)\n", i, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i])); + printf("\t-> ch %d => dl_ch0(%d,%d)\n", i, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i])); + } else { + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d) \t\t <==> DM-RS PDCCH, this is a pilot symbol\n", + c_rb, i, j, *(short *) &rxF_ext[j], *(1 + (short*) &rxF_ext[j]), i, + *(short *) &rxF[i], *(1 + (short*) &rxF[i])); + #endif + } + } + nb_rb++; + dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; + rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; + dl_ch0 += 12; + //rxF += 12; + //} + } + } + } +} + +#endif +#ifdef NR_PDCCH_DCI_RUN_bis +// this function is just a second implementation of nr_pdcch_extract_rbs_single +// the code modification is minimum but it can be slower in processing time +// to be removed + +void nr_pdcch_extract_rbs_single_bis(int32_t **rxdataF, int32_t **dl_ch_estimates, + int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, uint8_t symbol, + uint32_t high_speed_flag, NR_DL_FRAME_PARMS *frame_parms, uint64_t coreset_freq_dom, uint32_t coreset_nbr_rb, uint32_t n_BWP_start) { + + uint16_t rb, nb_rb = 0; + uint8_t i, j, aarx; + int32_t *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext; + int nushiftmod3 = frame_parms->nushift % 3; + uint8_t symbol_mod; + + symbol_mod = (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol; +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod); +#endif + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + if (high_speed_flag == 1){ + dl_ch0 = &dl_ch_estimates[aarx][5 + (symbol * (frame_parms->ofdm_symbol_size))]; + printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### dl_ch0 = &dl_ch_estimates[aarx = (%d) ][5 + (symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", + aarx,5 + (symbol * (frame_parms->ofdm_symbol_size))); + } else { + dl_ch0 = &dl_ch_estimates[aarx][5]; + printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### dl_ch0 = &dl_ch_estimates[aarx = (%d)][5]\n",aarx); + } + dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (frame_parms->N_RB_DL * 12)]; + printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 12) = (%d)]\n", + aarx,symbol * (frame_parms->N_RB_DL * 12)); + rxF_ext = &rxdataF_ext[aarx][symbol * (frame_parms->N_RB_DL * 12)]; + printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 12) = (%d)]\n", + aarx,symbol * (frame_parms->N_RB_DL * 12)); + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol * (frame_parms->ofdm_symbol_size)))]; + printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + aarx,(frame_parms->first_carrier_offset + (symbol * (frame_parms->ofdm_symbol_size)))); + printf("\t\t ###### in function pdcch_extract_rbs_single(for symbol=%d, aarx=%d), symbol_mod=%d, nushiftmod3=%d \n",symbol,aarx,symbol_mod,nushiftmod3); + printf("\t\t ###### rxF_ext = &rxdataF_ext[aarx(%d)][symbol(%d) * (frame_parms->N_RB_DL(%d) * 12)]\n",aarx,symbol,frame_parms->N_RB_DL); + printf("\t\t ###### rxF = &rxdataF[aarx(%d)][(frame_parms->first_carrier_offset(%d) + (symbol(%d) * (frame_parms->ofdm_symbol_size(%d))))]\n", + aarx,frame_parms->first_carrier_offset,symbol,frame_parms->ofdm_symbol_size); + + if ((frame_parms->N_RB_DL & 1) == 0) { // even number of RBs + for (rb = 0; rb < frame_parms->N_RB_DL; rb++) { + printf("\t\t\t ###### rb=%d\n",rb); + if (rb == (frame_parms->N_RB_DL >> 1)) { // For second half of RBs skip DC carrier + rxF = &rxdataF[aarx][(1 + (symbol * (frame_parms->ofdm_symbol_size)))]; + printf("\t\t\t ###### if rb (%d) is half N_RB_DL, skip DC carrier -> rxF = &rxdataF[aarx(%d)][(1 + (symbol(%d) * (frame_parms->ofdm_symbol_size(%d))))\n", + rb,aarx,symbol,frame_parms->ofdm_symbol_size); + //dl_ch0++; + } + if (symbol_mod > 0) { + memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); + for (i = 0; i < 12; i++) { + rxF_ext[i] = rxF[i]; + } + nb_rb++; + dl_ch0_ext += 12; + rxF_ext += 12; + dl_ch0 += 12; + rxF += 12; + } else { + j = 0; + for (i = 0; i < 12; i++) { + if ((i != 1) && (i != 5) && (i != 9)) { + rxF_ext[j] = rxF[i]; + printf("\textract rb %d \t re %d => rxF_ext[%d]=(%d,%d)", rb, i, j, *(short *) &rxF_ext[j], *(1 + (short*) &rxF_ext[j])); + dl_ch0_ext[j++] = dl_ch0[i]; + printf("\t\tch %d => dl_ch0(%d,%d)\n", i, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i])); + } + } + nb_rb++; + dl_ch0_ext += 9; + rxF_ext += 9; + dl_ch0 += 12; + rxF += 12; + } + } + } else { // Odd number of RBs + for (rb = 0; rb < frame_parms->N_RB_DL >> 1; rb++) { + printf("\t\t\t ###### rb=%d (Odd number of RBs, rb < half of band)\n",rb); + if (symbol_mod > 0) { + memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); + for (i = 0; i < 12; i++) + rxF_ext[i] = rxF[i]; + nb_rb++; + dl_ch0_ext += 12; + rxF_ext += 12; + dl_ch0 += 12; + rxF += 12; + } else { + j = 0; + for (i = 0; i < 12; i++) { + if ((i != 1) && (i != 5) && (i != 9)) { + rxF_ext[j] = rxF[i]; + printf("\t\t\t\t ###### extract rb %d, re %d => rxF_ext[%d]=(%d,%d) rxF[%d]=(%d,%d)", + rb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]),i,*(short *)&rxF[i],*(1+(short*)&rxF[i])); + dl_ch0_ext[j++] = dl_ch0[i]; + printf("\t ###### extract rb %d, re %d => dl_ch0 []=(%d,%d)\n",rb,i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); + } else { + printf("\t\t\t\t ###### THIS IS a pilot rb %d \t re %d => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d) \t this is a pilot symbol\n", + rb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]),i,*(short *)&rxF[i],*(1+(short*)&rxF[i])); + } + } + nb_rb++; + dl_ch0_ext += 9; + rxF_ext += 9; + dl_ch0 += 12; + rxF += 12; + } + } + // Do middle RB (around DC) + //printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); + if (symbol_mod == 0) { + j = 0; + for (i = 0; i < 6; i++) { + if ((i != 1) && (i != 5)) { + dl_ch0_ext[j] = dl_ch0[i]; + rxF_ext[j++] = rxF[i]; + //printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); + } + } + rxF = &rxdataF[aarx][((symbol * (frame_parms->ofdm_symbol_size)))]; + for (; i < 12; i++) { + if (i != 9) { + dl_ch0_ext[j] = dl_ch0[i]; + rxF_ext[j++] = rxF[(1 + i - 6)]; + //printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); + } + } + nb_rb++; + dl_ch0_ext += 9; + rxF_ext += 9; + dl_ch0 += 12; + rxF += 7; + rb++; + } else { + for (i = 0; i < 6; i++) { + dl_ch0_ext[i] = dl_ch0[i]; + rxF_ext[i] = rxF[i]; + } + rxF = &rxdataF[aarx][((symbol * (frame_parms->ofdm_symbol_size)))]; + for (; i < 12; i++) { + dl_ch0_ext[i] = dl_ch0[i]; + rxF_ext[i] = rxF[(1 + i - 6)]; + } + nb_rb++; + dl_ch0_ext += 12; + rxF_ext += 12; + dl_ch0 += 12; + rxF += 7; + rb++; + } + for (; rb < frame_parms->N_RB_DL; rb++) { + printf("\t\t\t ###### rb=%d (Even number of RBs, rb > half of band)\n",rb); + if (symbol_mod > 0) { + memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); + for (i = 0; i < 12; i++) + rxF_ext[i] = rxF[i]; + nb_rb++; + dl_ch0_ext += 12; + rxF_ext += 12; + dl_ch0 += 12; + rxF += 12; + } else { + j = 0; + for (i = 0; i < 12; i++) { + if ((i != 1) && (i != 5) && (i != 9)) { + rxF_ext[j] = rxF[i]; + printf("\t\t\t\t ###### extract rb %d, re %d => rxF_ext[]=(%d,%d)",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + //printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + dl_ch0_ext[j++] = dl_ch0[i]; + printf("\t ###### extract rb %d, re %d => dl_ch0 []=(%d,%d)\n",rb,i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); + } else { + printf("\t\t\t\t ###### THIS IS a RS at re %d\n",i); + } + } + nb_rb++; + dl_ch0_ext += 9; + rxF_ext += 9; + dl_ch0 += 12; + rxF += 12; + } + } + } + } + +// The function has created table rxdataF_ext with the contents of rxdataF and removing the pilots at positions 1,5,9 in every RB. +// Now we need to check the contents of rxdataF_ext and keep only the values which correspond to our CORESET depending on variables: +// - coreset_freq_dom (45 bit map) +// - n_BWP_start (first RB within the active BWP and the CORESET) + j=0; + k=0; + rxF_ext = &rxdataF_ext[aarx][(symbol * (frame_parms->N_RB_DL * 12))]; + printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### rxF_ext = &rxdataF_ext[aarx = (%d)][n_BWP_start + (symbol * (frame_parms->N_RB_DL * 12)) = (%d)]\n", + aarx,(n_BWP_start + (symbol * (frame_parms->N_RB_DL * 12)))); + + int bitcnt_coreset_freq_dom = 1; // this variable will allow to check each bit of the 45 bitmap coreset_freq_dom. + //Eg: if bitcnt_coreset_freq_dom = 3, (46-3) we verify bit 43 starting from LSB + for (rb=0; rb<frame_parms->N_RB_DL;rb++) { + if (rb < n_BWP_start) { + // while rb is not within CORESET, then remove values + for (i=0; i<8; i++) { + //rxF_ext[i] = 0; + j++; + } + //rxF_ext = &rxdataF_ext[aarx][(j + (symbol * (frame_parms->N_RB_DL * 12)))]; + } else if ((rb >= n_BWP_start) && (rb < (n_BWP_start + 6 * 45))) { + // rb is within CORESET, we need to verify now whether bit in coreset_freq_dom is set or not + if ((((coreset_freq_dom & 0x1FFFFFFFFFFF) >> (46 - bitcnt_coreset_freq_dom)) & 0x1)== 0){ + // if bit is 0, next 6 consecutive RBs do not belong to CORESET + bitcnt_coreset_freq_dom ++; + rb = rb + 6; + for (i=0; i<(9*6); i++) { + //rxF_ext[i] = 0; + j++; + } + //rxF_ext = &rxdataF_ext[aarx][(j + (symbol * (frame_parms->N_RB_DL * 12)))]; + } else { + // if bit is 1, next 6 consecutive RBs belong to CORESET + bitcnt_coreset_freq_dom ++; + rb = rb + 6; + for (i=0; i<(9*6); i++) { + rxF_ext[k] = rxF_ext[j]; + k++; + j++; + } + //rxF_ext = &rxdataF_ext[aarx][(j + (symbol * (frame_parms->N_RB_DL * 12)))]; + } + } else { // for the RBs that are in the upper side of the CORESET bitmap + for (i=0; i<8; i++) { + rxF_ext[k] = 0; + k++; + j++; + } + //rxF_ext = &rxdataF_ext[aarx][(j + (symbol * (frame_parms->N_RB_DL * 12)))]; + } + } +} + +#endif + + + +void pdcch_extract_rbs_single(int32_t **rxdataF, + int32_t **dl_ch_estimates, + int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + uint8_t symbol, + uint32_t high_speed_flag, + NR_DL_FRAME_PARMS *frame_parms) +{ + + + uint16_t rb,nb_rb=0; + uint8_t i,j,aarx; + int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; + + + int nushiftmod3 = frame_parms->nushift%3; + uint8_t symbol_mod; + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod); +#endif + + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + + if (high_speed_flag == 1) + dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; + else + dl_ch0 = &dl_ch_estimates[aarx][5]; + + dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; + + rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; + + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; + + if ((frame_parms->N_RB_DL&1) == 0) { // even number of RBs + for (rb=0; rb<frame_parms->N_RB_DL; rb++) { + + // For second half of RBs skip DC carrier + if (rb==(frame_parms->N_RB_DL>>1)) { + rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; + + //dl_ch0++; + } + + if (symbol_mod>0) { + memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); + + for (i=0; i<12; i++) { + + rxF_ext[i]=rxF[i]; + + } + + nb_rb++; + dl_ch0_ext+=12; + rxF_ext+=12; + + dl_ch0+=12; + rxF+=12; + } else { + j=0; + + for (i=0; i<12; i++) { + if ((i!=nushiftmod3) && + (i!=(nushiftmod3+3)) && + (i!=(nushiftmod3+6)) && + (i!=(nushiftmod3+9))) { + rxF_ext[j]=rxF[i]; + // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + dl_ch0_ext[j++]=dl_ch0[i]; + // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); + } + } + + nb_rb++; + dl_ch0_ext+=8; + rxF_ext+=8; + + dl_ch0+=12; + rxF+=12; + } + } + } else { // Odd number of RBs + for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) { + + if (symbol_mod>0) { + memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); + + for (i=0; i<12; i++) + rxF_ext[i]=rxF[i]; + + nb_rb++; + dl_ch0_ext+=12; + rxF_ext+=12; + + dl_ch0+=12; + rxF+=12; + } else { + j=0; + + for (i=0; i<12; i++) { + if ((i!=nushiftmod3) && + (i!=(nushiftmod3+3)) && + (i!=(nushiftmod3+6)) && + (i!=(nushiftmod3+9))) { + rxF_ext[j]=rxF[i]; + // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + dl_ch0_ext[j++]=dl_ch0[i]; + // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); + } + } + + nb_rb++; + dl_ch0_ext+=8; + rxF_ext+=8; + + dl_ch0+=12; + rxF+=12; + } + } + + // Do middle RB (around DC) + // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); + + if (symbol_mod==0) { + j=0; + + for (i=0; i<6; i++) { + if ((i!=nushiftmod3) && + (i!=(nushiftmod3+3))) { + dl_ch0_ext[j]=dl_ch0[i]; + rxF_ext[j++]=rxF[i]; + // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); + } + } + + rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; + + for (; i<12; i++) { + if ((i!=(nushiftmod3+6)) && + (i!=(nushiftmod3+9))) { + dl_ch0_ext[j]=dl_ch0[i]; + rxF_ext[j++]=rxF[(1+i-6)]; + // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); + } + } + + + nb_rb++; + dl_ch0_ext+=8; + rxF_ext+=8; + dl_ch0+=12; + rxF+=7; + rb++; + } else { + for (i=0; i<6; i++) { + dl_ch0_ext[i]=dl_ch0[i]; + rxF_ext[i]=rxF[i]; + } + + rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; + + for (; i<12; i++) { + dl_ch0_ext[i]=dl_ch0[i]; + rxF_ext[i]=rxF[(1+i-6)]; + } + + + nb_rb++; + dl_ch0_ext+=12; + rxF_ext+=12; + dl_ch0+=12; + rxF+=7; + rb++; + } + + for (; rb<frame_parms->N_RB_DL; rb++) { + if (symbol_mod > 0) { + memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); + + for (i=0; i<12; i++) + rxF_ext[i]=rxF[i]; + + nb_rb++; + dl_ch0_ext+=12; + rxF_ext+=12; + + dl_ch0+=12; + rxF+=12; + } else { + j=0; + + for (i=0; i<12; i++) { + if ((i!=(nushiftmod3)) && + (i!=(nushiftmod3+3)) && + (i!=(nushiftmod3+6)) && + (i!=(nushiftmod3+9))) { + rxF_ext[j]=rxF[i]; + // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + dl_ch0_ext[j++]=dl_ch0[i]; + } + } + + nb_rb++; + dl_ch0_ext+=8; + rxF_ext+=8; + + dl_ch0+=12; + rxF+=12; + } + } + } + } +} + +void pdcch_extract_rbs_dual(int32_t **rxdataF, + int32_t **dl_ch_estimates, + int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + uint8_t symbol, + uint32_t high_speed_flag, + NR_DL_FRAME_PARMS *frame_parms) +{ + + + uint16_t rb,nb_rb=0; + uint8_t i,aarx,j; + int32_t *dl_ch0,*dl_ch0_ext,*dl_ch1,*dl_ch1_ext,*rxF,*rxF_ext; + uint8_t symbol_mod; + int nushiftmod3 = frame_parms->nushift%3; + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY, "extract_rbs_dual: symbol_mod %d\n",symbol_mod); +#endif + + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + + if (high_speed_flag==1) { + dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; + dl_ch1 = &dl_ch_estimates[2+aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; + } else { + dl_ch0 = &dl_ch_estimates[aarx][5]; + dl_ch1 = &dl_ch_estimates[2+aarx][5]; + } + + dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; + dl_ch1_ext = &dl_ch_estimates_ext[2+aarx][symbol*(frame_parms->N_RB_DL*12)]; + + // printf("pdcch extract_rbs: rxF_ext pos %d\n",symbol*(frame_parms->N_RB_DL*12)); + rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; + + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; + + if ((frame_parms->N_RB_DL&1) == 0) // even number of RBs + for (rb=0; rb<frame_parms->N_RB_DL; rb++) { + + // For second half of RBs skip DC carrier + if (rb==(frame_parms->N_RB_DL>>1)) { + rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; + // dl_ch0++; + //dl_ch1++; + } + + if (symbol_mod>0) { + memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); + memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); + + /* + printf("rb %d\n",rb); + for (i=0;i<12;i++) + printf("(%d %d)",((int16_t *)dl_ch0)[i<<1],((int16_t*)dl_ch0)[1+(i<<1)]); + printf("\n"); + */ + for (i=0; i<12; i++) { + rxF_ext[i]=rxF[i]; + // printf("%d : (%d,%d)\n",(rxF+(2*i)-&rxdataF[aarx][( (symbol*(frame_parms->ofdm_symbol_size)))*2])/2, + // ((int16_t*)&rxF[i<<1])[0],((int16_t*)&rxF[i<<1])[0]); + } + + nb_rb++; + dl_ch0_ext+=12; + dl_ch1_ext+=12; + rxF_ext+=12; + } else { + j=0; + + for (i=0; i<12; i++) { + if ((i!=nushiftmod3) && + (i!=nushiftmod3+3) && + (i!=nushiftmod3+6) && + (i!=nushiftmod3+9)) { + rxF_ext[j]=rxF[i]; + // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + dl_ch0_ext[j] =dl_ch0[i]; + dl_ch1_ext[j++]=dl_ch1[i]; + } + } + + nb_rb++; + dl_ch0_ext+=8; + dl_ch1_ext+=8; + rxF_ext+=8; + } + + dl_ch0+=12; + dl_ch1+=12; + rxF+=12; + } + + else { // Odd number of RBs + for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) { + + // printf("rb %d: %d\n",rb,rxF-&rxdataF[aarx][(symbol*(frame_parms->ofdm_symbol_size))*2]); + + if (symbol_mod>0) { + memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); + memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); + + for (i=0; i<12; i++) + rxF_ext[i]=rxF[i]; + + nb_rb++; + dl_ch0_ext+=12; + dl_ch1_ext+=12; + rxF_ext+=12; + + dl_ch0+=12; + dl_ch1+=12; + rxF+=12; + + } else { + j=0; + + for (i=0; i<12; i++) { + if ((i!=nushiftmod3) && + (i!=nushiftmod3+3) && + (i!=nushiftmod3+6) && + (i!=nushiftmod3+9)) { + rxF_ext[j]=rxF[i]; + // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + dl_ch0_ext[j]=dl_ch0[i]; + dl_ch1_ext[j++]=dl_ch1[i]; + // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); + } + } + + nb_rb++; + dl_ch0_ext+=8; + dl_ch1_ext+=8; + rxF_ext+=8; + + + dl_ch0+=12; + dl_ch1+=12; + rxF+=12; + } + } + + // Do middle RB (around DC) + + if (symbol_mod > 0) { + for (i=0; i<6; i++) { + dl_ch0_ext[i]=dl_ch0[i]; + dl_ch1_ext[i]=dl_ch1[i]; + rxF_ext[i]=rxF[i]; + } + + rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; + + for (; i<12; i++) { + dl_ch0_ext[i]=dl_ch0[i]; + dl_ch1_ext[i]=dl_ch1[i]; + rxF_ext[i]=rxF[(1+i)]; + } + + nb_rb++; + dl_ch0_ext+=12; + dl_ch1_ext+=12; + rxF_ext+=12; + + dl_ch0+=12; + dl_ch1+=12; + rxF+=7; + rb++; + } else { + j=0; + + for (i=0; i<6; i++) { + if ((i!=nushiftmod3) && + (i!=nushiftmod3+3)) { + dl_ch0_ext[j]=dl_ch0[i]; + dl_ch1_ext[j]=dl_ch1[i]; + rxF_ext[j++]=rxF[i]; + // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); + } + } + + rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; + + for (; i<12; i++) { + if ((i!=nushiftmod3+6) && + (i!=nushiftmod3+9)) { + dl_ch0_ext[j]=dl_ch0[i]; + dl_ch1_ext[j]=dl_ch1[i]; + rxF_ext[j++]=rxF[(1+i-6)]; + // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); + } + } + + + nb_rb++; + dl_ch0_ext+=8; + dl_ch1_ext+=8; + rxF_ext+=8; + dl_ch0+=12; + dl_ch1+=12; + rxF+=7; + rb++; + } + + for (; rb<frame_parms->N_RB_DL; rb++) { + + if (symbol_mod>0) { + // printf("rb %d: %d\n",rb,rxF-&rxdataF[aarx][(symbol*(frame_parms->ofdm_symbol_size))*2]); + memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); + memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); + + for (i=0; i<12; i++) + rxF_ext[i]=rxF[i]; + + nb_rb++; + dl_ch0_ext+=12; + dl_ch1_ext+=12; + rxF_ext+=12; + + dl_ch0+=12; + dl_ch1+=12; + rxF+=12; + } else { + j=0; + + for (i=0; i<12; i++) { + if ((i!=nushiftmod3) && + (i!=nushiftmod3+3) && + (i!=nushiftmod3+6) && + (i!=nushiftmod3+9)) { + rxF_ext[j]=rxF[i]; + // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + dl_ch0_ext[j]=dl_ch0[i]; + dl_ch1_ext[j++]=dl_ch1[i]; + } + } + + nb_rb++; + dl_ch0_ext+=8; + dl_ch1_ext+=8; + rxF_ext+=8; + + dl_ch0+=12; + dl_ch1+=12; + rxF+=12; + } + } + } + } +} + + + +#ifdef NR_PDCCH_DCI_RUN +void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + int32_t **rxdataF_comp, + int32_t **rho, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t symbol, + uint8_t output_shift, + uint32_t coreset_nbr_rb) +{ + + uint16_t rb; + #if defined(__x86_64__) || defined(__i386__) + __m128i *dl_ch128, *rxdataF128, *rxdataF_comp128; + __m128i *dl_ch128_2, *rho128; + #elif defined(__arm__) + #endif + uint8_t aatx, aarx, pilots = 0; + +short conjugate[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1}; +short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; + + #ifdef DEBUG_DCI_DECODING + LOG_I(PHY, "PDCCH comp: symbol %d\n",symbol); + #endif +/* + if (symbol == 0) + pilots = 1; +*/ + for (aatx = 0; aatx < frame_parms->nb_antenna_ports_eNB; aatx++) { + //if (frame_parms->mode1_flag && aatx>0) break; //if mode1_flag is set then there is only one stream to extract, independent of nb_antenna_ports_eNB + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + #if defined(__x86_64__) || defined(__i386__) + // dl_ch128 = (__m128i *) &dl_ch_estimates_ext[(aatx << 1) + aarx][symbol * frame_parms->N_RB_DL * 12]; + // rxdataF128 = (__m128i *) &rxdataF_ext[aarx][symbol * frame_parms->N_RB_DL * 12]; + // rxdataF_comp128 = (__m128i *) &rxdataF_comp[(aatx << 1) + aarx][symbol * frame_parms->N_RB_DL * 12]; + dl_ch128 = (__m128i *) &dl_ch_estimates_ext[(aatx << 1) + aarx][symbol * coreset_nbr_rb * 12]; + rxdataF128 = (__m128i *) &rxdataF_ext[aarx][symbol * coreset_nbr_rb * 12]; + rxdataF_comp128 = (__m128i *) &rxdataF_comp[(aatx << 1) + aarx][symbol * coreset_nbr_rb * 12]; + #elif defined(__arm__) + #endif + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> Total of RBs to be computed (%d), and number of RE (%d) (9 RE per RB)\n",coreset_nbr_rb,coreset_nbr_rb*9); + #endif + uint32_t k=0; + for (rb = 0; rb < coreset_nbr_rb; rb) { //FIXME this for loop risks an infinite loop if rb is not increased by 1 inside the loop + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rb=%d\n", rb); + #endif + #if defined(__x86_64__) || defined(__i386__) + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[0], rxdataF128[0]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + // print_ints("re",&mmtmpPD0); + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0], _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1, _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1, *(__m128i * )&conjugate[0]); + // print_ints("im",&mmtmpPD1); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1, rxdataF128[0]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0, output_shift); + // print_ints("re(shift)",&mmtmpPD0); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1, output_shift); + // print_ints("im(shift)",&mmtmpPD1); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0, mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0, mmtmpPD1); + // print_ints("c0",&mmtmpPD2); + // print_ints("c1",&mmtmpPD3); + rxdataF_comp128[0] = _mm_packs_epi32(mmtmpPD2, mmtmpPD3); + // print_shorts("rx:",rxdataF128); + // print_shorts("ch:",dl_ch128); + // print_shorts("pack:",rxdataF_comp128); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[1], rxdataF128[1]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1], _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1, _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1, *(__m128i * )conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1, rxdataF128[1]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0, output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1, output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0, mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0, mmtmpPD1); + rxdataF_comp128[1] = _mm_packs_epi32(mmtmpPD2, mmtmpPD3); + // print_shorts("rx:",rxdataF128+1); + // print_shorts("ch:",dl_ch128+1); + // print_shorts("pack:",rxdataF_comp128+1); + // multiply by conjugated channel + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF x dl_ch -> RB[%d] RE[%d]\n",rb,k); + #endif + k++; + if (k%9 == 0) rb++; + mmtmpPD0 = _mm_madd_epi16(dl_ch128[2], rxdataF128[2]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1, _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1, *(__m128i * )conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1, rxdataF128[2]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0, output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1, output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0, mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0, mmtmpPD1); + rxdataF_comp128[2] = _mm_packs_epi32(mmtmpPD2, mmtmpPD3); + // We compute the third part of 4 symbols contained in one entire RB = 12 RE + //if (rb < 6 || rb > 95) { + #ifdef NR_PDCCH_DCI_DEBUG + print_shorts("\t\trxdataF_ext:", rxdataF128); + print_shorts("\t\tdl_ch:", dl_ch128); + print_shorts("\t\trxdataF_comp:", rxdataF_comp128); + print_shorts("\t\trxdataF_ext:", rxdataF128 + 1); + print_shorts("\t\tdl_ch:", dl_ch128 + 1); + print_shorts("\t\trxdataF_comp:", rxdataF_comp128 + 1); + print_shorts("\t\ttrxdataF_ext:", rxdataF128 + 2); + print_shorts("\t\tdl_ch:", dl_ch128 + 2); + print_shorts("\t\trxdataF_comp:", rxdataF_comp128 + 2); + #endif + //} + dl_ch128 += 3; + rxdataF128 += 3; + rxdataF_comp128 += 3; + //if ((rb + 1) % 4 == 3) + //rb++; + // if rxdataF_comp does contains pilot DM-RS PDCCH, as in previous code rxdataF_comp128 is a set of 4 consecutive outputs (32-bit) + // the computation of third part of 4 symbols contains last 9th symbol of the current rb + 3 first symbols of the next rb + // so rb computing must be take this into consideration, and every 4 rb, rb must be increased twice + //} + +// This code will replace the code below for nr +//#else +/* + if (pilots == 0) { + mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); + // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[2]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + + rxdataF_comp128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); + } + + print_shorts("rx:",rxdataF128); + print_shorts("ch:",dl_ch128); + print_shorts("pack:",rxdataF_comp128); + print_shorts("\trx:",rxdataF128+1); + print_shorts("\tch:",dl_ch128+1); + print_shorts("\tpack:",rxdataF_comp128+1); + print_shorts("\t\trx:",rxdataF128+2); + print_shorts("\t\tch:",dl_ch128+2); + print_shorts("\t\tpack:",rxdataF_comp128+2); + + if (pilots==0) { + dl_ch128+=3; + rxdataF128+=3; + rxdataF_comp128+=3; + } else { + dl_ch128+=2; + rxdataF128+=2; + rxdataF_comp128+=2; + } + +*/ +//#endif + +#elif defined(__arm__) + +#endif + } + } + } + + if (rho) { + + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + +#if defined(__x86_64__) || defined(__i386__) + rho128 = (__m128i *) &rho[aarx][symbol * frame_parms->N_RB_DL * 12]; + dl_ch128 = (__m128i *) &dl_ch_estimates_ext[aarx][symbol + * frame_parms->N_RB_DL * 12]; + dl_ch128_2 = (__m128i *) &dl_ch_estimates_ext[2 + aarx][symbol + * frame_parms->N_RB_DL * 12]; + +#elif defined(__arm__) + +#endif + +//for (rb = 0; rb < frame_parms->N_RB_DL; rb++) { +for (rb = 0; rb < coreset_nbr_rb; rb++) { +#if defined(__x86_64__) || defined(__i386__) + + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[0], dl_ch128_2[0]); + // print_ints("re",&mmtmpD0); + + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0], + _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1, _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1, *(__m128i * )&conjugate[0]); + // print_ints("im",&mmtmpPD1); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1, dl_ch128_2[0]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0, output_shift); + // print_ints("re(shift)",&mmtmpD0); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1, output_shift); + // print_ints("im(shift)",&mmtmpD1); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0, mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0, mmtmpPD1); + // print_ints("c0",&mmtmpPD2); + // print_ints("c1",&mmtmpPD3); + rho128[0] = _mm_packs_epi32(mmtmpPD2, mmtmpPD3); + + //print_shorts("rx:",dl_ch128_2); + //print_shorts("ch:",dl_ch128); + //print_shorts("pack:",rho128); + + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[1], dl_ch128_2[1]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1], + _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1, _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1, *(__m128i * )conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1, dl_ch128_2[1]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0, output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1, output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0, mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0, mmtmpPD1); + + rho128[1] = _mm_packs_epi32(mmtmpPD2, mmtmpPD3); + //print_shorts("rx:",dl_ch128_2+1); + //print_shorts("ch:",dl_ch128+1); + //print_shorts("pack:",rho128+1); + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[2], dl_ch128_2[2]); + // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2], + _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1, _MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1, *(__m128i * )conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1, dl_ch128_2[2]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0, output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1, output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0, mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0, mmtmpPD1); + + rho128[2] = _mm_packs_epi32(mmtmpPD2, mmtmpPD3); + //print_shorts("rx:",dl_ch128_2+2); + //print_shorts("ch:",dl_ch128+2); + //print_shorts("pack:",rho128+2); + + dl_ch128 += 3; + dl_ch128_2 += 3; + rho128 += 3; + +#elif defined(__arm_) + +#endif + } + } + + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif +} + +#endif + +/* +void pdcch_channel_compensation(int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + int32_t **rxdataF_comp, + int32_t **rho, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t symbol, + uint8_t output_shift) +{ + + uint16_t rb; +#if defined(__x86_64__) || defined(__i386__) + __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128; + __m128i *dl_ch128_2, *rho128; +#elif defined(__arm__) + +#endif + uint8_t aatx,aarx,pilots=0; + + + + +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY, "PDCCH comp: symbol %d\n",symbol); +#endif + + if (symbol==0) + pilots=1; + + for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { + //if (frame_parms->mode1_flag && aatx>0) break; //if mode1_flag is set then there is only one stream to extract, independent of nb_antenna_ports_eNB + + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + +#if defined(__x86_64__) || defined(__i386__) + dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; + rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; +#elif defined(__arm__) + +#endif + + for (rb=0; rb<frame_parms->N_RB_DL; rb++) { + +#if defined(__x86_64__) || defined(__i386__) + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]); + // print_ints("re",&mmtmpPD0); + + // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); + // print_ints("im",&mmtmpPD1); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[0]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + // print_ints("re(shift)",&mmtmpPD0); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + // print_ints("im(shift)",&mmtmpPD1); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + // print_ints("c0",&mmtmpPD2); + // print_ints("c1",&mmtmpPD3); + rxdataF_comp128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); + // print_shorts("rx:",rxdataF128); + // print_shorts("ch:",dl_ch128); + // print_shorts("pack:",rxdataF_comp128); + + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); + // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[1]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + + rxdataF_comp128[1] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); + + // print_shorts("rx:",rxdataF128+1); + // print_shorts("ch:",dl_ch128+1); + // print_shorts("pack:",rxdataF_comp128+1); + // multiply by conjugated channel + if (pilots == 0) { + mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); + // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[2]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + + rxdataF_comp128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); + } + + // print_shorts("rx:",rxdataF128+2); + // print_shorts("ch:",dl_ch128+2); + // print_shorts("pack:",rxdataF_comp128+2); + + if (pilots==0) { + dl_ch128+=3; + rxdataF128+=3; + rxdataF_comp128+=3; + } else { + dl_ch128+=2; + rxdataF128+=2; + rxdataF_comp128+=2; + } +#elif defined(__arm__) + +#endif + } + } + } + + + if (rho) { + + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + +#if defined(__x86_64__) || defined(__i386__) + rho128 = (__m128i *)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; + dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; + dl_ch128_2 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; + +#elif defined(__arm__) + +#endif + for (rb=0; rb<frame_parms->N_RB_DL; rb++) { +#if defined(__x86_64__) || defined(__i386__) + + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128_2[0]); + // print_ints("re",&mmtmpD0); + + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); + // print_ints("im",&mmtmpPD1); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[0]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + // print_ints("re(shift)",&mmtmpD0); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + // print_ints("im(shift)",&mmtmpD1); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + // print_ints("c0",&mmtmpPD2); + // print_ints("c1",&mmtmpPD3); + rho128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); + + //print_shorts("rx:",dl_ch128_2); + //print_shorts("ch:",dl_ch128); + //print_shorts("pack:",rho128); + + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128_2[1]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[1]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + + + rho128[1] =_mm_packs_epi32(mmtmpPD2,mmtmpPD3); + //print_shorts("rx:",dl_ch128_2+1); + //print_shorts("ch:",dl_ch128+1); + //print_shorts("pack:",rho128+1); + // multiply by conjugated channel + mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128_2[2]); + // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); + mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[2]); + // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); + mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); + mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); + mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); + + rho128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); + //print_shorts("rx:",dl_ch128_2+2); + //print_shorts("ch:",dl_ch128+2); + //print_shorts("pack:",rho128+2); + + dl_ch128+=3; + dl_ch128_2+=3; + rho128+=3; + +#elif defined(__arm_) + + +#endif + } + } + + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif +} +*/ +void pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + uint8_t symbol) +{ + + uint8_t aatx; + +#if defined(__x86_64__) || defined(__i386__) + __m128i *rxdataF_comp128_0,*rxdataF_comp128_1; +#elif defined(__arm__) + int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1; +#endif + int32_t i; + + if (frame_parms->nb_antennas_rx>1) { + for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { +#if defined(__x86_64__) || defined(__i386__) + rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; +#elif defined(__arm__) + rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; +#endif + // MRC on each re of rb + for (i=0; i<frame_parms->N_RB_DL*3; i++) { +#if defined(__x86_64__) || defined(__i386__) + rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); +#elif defined(__arm__) + rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]); +#endif + } + } + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif + +} + +void pdcch_siso(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + uint8_t l) +{ + + + uint8_t rb,re,jj,ii; + + jj=0; + ii=0; + + for (rb=0; rb<frame_parms->N_RB_DL; rb++) { + + for (re=0; re<12; re++) { + + rxdataF_comp[0][jj++] = rxdataF_comp[0][ii]; + ii++; + } + } +} + + +void pdcch_alamouti(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + uint8_t symbol) +{ + + + int16_t *rxF0,*rxF1; + uint8_t rb,re; + int32_t jj=(symbol*frame_parms->N_RB_DL*12); + + rxF0 = (int16_t*)&rxdataF_comp[0][jj]; //tx antenna 0 h0*y + rxF1 = (int16_t*)&rxdataF_comp[2][jj]; //tx antenna 1 h1*y + + for (rb=0; rb<frame_parms->N_RB_DL; rb++) { + + for (re=0; re<12; re+=2) { + + // Alamouti RX combining + + rxF0[0] = rxF0[0] + rxF1[2]; + rxF0[1] = rxF0[1] - rxF1[3]; + + rxF0[2] = rxF0[2] - rxF1[0]; + rxF0[3] = rxF0[3] + rxF1[1]; + + rxF0+=4; + rxF1+=4; + } + } + + +} + +int32_t avgP[4]; + + + + +#ifdef NR_PDCCH_DCI_RUN +int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, + uint32_t frame, + uint8_t nr_tti_rx, + uint8_t eNB_id, + MIMO_mode_t mimo_mode, + uint32_t high_speed_flag, + uint8_t is_secondary_ue, + int nb_coreset_active, + uint16_t symbol_mon, + int do_common) { + + #ifdef MU_RECEIVER + uint8_t eNB_id_i=eNB_id+1; //add 1 to eNB_id to separate from wanted signal, chosen as the B/F'd pilots from the SeNB are shifted by 1 +#endif + + NR_UE_COMMON *common_vars = &ue->common_vars; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; + NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; + + uint8_t log2_maxh, aatx, aarx; + int32_t avgs; + uint8_t n_pdcch_symbols; + // the variable mi can be removed for NR + uint8_t mi = get_mi(frame_parms, nr_tti_rx); + +/* + * The following variables have been extracted from higher layer parameters + * MIB1 => pdcchConfigSIB1 + * ControlResourceSet IE + * pdcch-Config + * pdcch-ConfigCommon + */ + +/* + * initialize this values for testing + */ +#if 0 + pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources = 0x1FFF2FF00000; + //pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources = 0x1E0000000000; + pdcch_vars2->coreset[nb_coreset_active].duration = 2; + pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.shiftIndex = 0; + pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.reg_bundlesize = bundle_n6; + pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.interleaversize = interleave_n2; + pdcch_vars2->coreset[nb_coreset_active].pdcchDMRSScramblingID = 1; + for (int i=0; i < NR_NBR_SEARCHSPACE_ACT_BWP; i++){ + pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel1 = 7; + pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel2 = 6; + pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel4 = 4; + pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel8 = 3; + pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel16 = 1; + pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel1 = 7; + pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel2 = 6; + pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel4 = 4; + pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel8 = 3; + pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel16 = 1; + } +#endif //(0) +/* + * to be removed after testing + */ + + // number of RB (1 symbol) or REG (12 RE) in one CORESET: higher-layer parameter CORESET-freq-dom + // (bit map 45 bits: each bit indicates 6 RB in CORESET -> 1 bit MSB indicates PRB 0..6 are part of CORESET) + uint64_t coreset_freq_dom = pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources; + // number of symbols in CORESET: higher-layer parameter CORESET-time-dur {1,2,3} + int coreset_time_dur = pdcch_vars2->coreset[nb_coreset_active].duration; + // depends on higher-layer parameter CORESET-shift-index {0,1,...,274} + int n_shift = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.shiftIndex; + // higher-layer parameter CORESET-REG-bundle-size (for non-interleaved L = 6 / for interleaved L {2,6}) + NR_UE_CORESET_REG_bundlesize_t reg_bundle_size_L = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.reg_bundlesize; + // higher-layer parameter CORESET-interleaver-size {2,3,6} + NR_UE_CORESET_interleaversize_t coreset_interleaver_size_R= pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.interleaversize; + NR_UE_CORESET_precoder_granularity_t precoder_granularity = pdcch_vars2->coreset[nb_coreset_active].precoderGranularity; + int tci_statesPDCCH = pdcch_vars2->coreset[nb_coreset_active].tciStatesPDCCH; + int tci_present = pdcch_vars2->coreset[nb_coreset_active].tciPresentInDCI; + uint16_t pdcch_DMRS_scrambling_id = pdcch_vars2->coreset[nb_coreset_active].pdcchDMRSScramblingID; + + // The UE can be assigned 4 different BWP but only one active at a time. + // For each BWP the number of CORESETs is limited to 3 (including initial CORESET Id=0 -> ControlResourceSetId (0..maxNrofControlReourceSets-1) (0..12-1) + uint32_t n_BWP_start = 0; + // start time position for CORESET + // parameter symbol_mon is a 14 bits bitmap indicating monitoring symbols within a slot + uint8_t start_symbol = 0; + + // at the moment we are considering that the PDCCH is always starting at symbol 0 of current slot + // the following code to initialize start_symbol must be activated once we implement PDCCH demapping on symbol not equal to 0 (considering symbol_mon) + /*for (int i=0; i < 14; i++) { + if (symbol_mon >> (13-i) != 0) { + start_symbol = i; + i=14; + } + }*/ + + // + // according to 38.213 v15.1.0: a PDCCH monitoring pattern within a slot, + // indicating first symbol(s) of the control resource set within a slot + // for PDCCH monitoring, by higher layer parameter monitoringSymbolsWithinSlot + // + // at the moment we do not implement this and start_symbol is always 0 + // note that the bitmap symbol_mon may indicate several monitoring times within a same slot (symbols 0..13) + // this may lead to a modification in ue scheduler + + // indicates the number of active CORESETs for the current BWP to decode PDCCH: max is 3 (this variable is not useful here, to be removed) + uint8_t coreset_nbr_act; + // indicates the number of REG contained in the PDCCH (number of RBs * number of symbols, in CORESET) + uint8_t coreset_nbr_reg; + uint32_t coreset_C; + uint32_t coreset_nbr_rb = 0; + + // for (int j=0; j < coreset_nbr_act; j++) { + // for each active CORESET (max number of active CORESETs in a BWP is 3), + // we calculate the number of RB for each CORESET bitmap + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%lld)\n",coreset_freq_dom); + #endif + int i; //for each bit in the coreset_freq_dom bitmap + for (i = 0; i < 45; i++) { + // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' + if (((coreset_freq_dom & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_rb++; + } + coreset_nbr_rb = 6 * coreset_nbr_rb; // coreset_nbr_rb has to be multiplied by 6 to indicate the number of PRB or REG(=12 RE) within the CORESET + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%lld,%llx), coreset_nbr_rb=%d\n", coreset_freq_dom,coreset_freq_dom,coreset_nbr_rb); + #endif + coreset_nbr_reg = coreset_time_dur * coreset_nbr_rb; + coreset_C = (uint32_t)(coreset_nbr_reg / (reg_bundle_size_L * coreset_interleaver_size_R)); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_nbr_rb=%d, coreset_nbr_reg=%d, coreset_C=(%d/(%d*%d))=%d\n", + coreset_nbr_rb, coreset_nbr_reg, coreset_nbr_reg, reg_bundle_size_L,coreset_interleaver_size_R, coreset_C); + #endif + + for (int s = start_symbol; s < (start_symbol + coreset_time_dur); s++) { + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter process pdcch ofdm symbol s=%d where coreset_time_dur=%d\n",s,coreset_time_dur); + + if (is_secondary_ue == 1) { + pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, + common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id+1], //add 1 to eNB_id to compensate for the shifted B/F'd pilots from the SeNB + pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + 0, + high_speed_flag, + frame_parms); +#ifdef MU_RECEIVER + pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, + common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id_i - 1], //subtract 1 to eNB_id_i to compensate for the non-shifted pilots from the PeNB + pdcch_vars[eNB_id_i]->rxdataF_ext,//shift by two to simulate transmission from a second antenna + pdcch_vars[eNB_id_i]->dl_ch_estimates_ext,//shift by two to simulate transmission from a second antenna + 0, + high_speed_flag, + frame_parms); +#endif //MU_RECEIVER + } else if (frame_parms->nb_antenna_ports_eNB>1) { + pdcch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, + common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id], + pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + 0, + high_speed_flag, + frame_parms); + } else { + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_extract_rbs_single(is_secondary_ue=%d) to remove DM-RS PDCCH\n", + is_secondary_ue); + #endif + nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, + common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id], + pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + s, + high_speed_flag, + frame_parms, + coreset_freq_dom, + coreset_nbr_rb, + n_BWP_start); +/* + printf("\t### in nr_rx_pdcch() function we enter pdcch_extract_rbs_single(is_secondary_ue=%d) to remove DM-RS PDCCH\n",is_secondary_ue); + pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, + common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id], + pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + 0, + high_speed_flag, + frame_parms); +*/ + +} + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",avgP); + #endif + // compute channel level based on ofdm symbol 0 + pdcch_channel_level(pdcch_vars[eNB_id]->dl_ch_estimates_ext, + frame_parms, + avgP, + frame_parms->N_RB_DL); + avgs = 0; + for (aatx = 0; aatx < frame_parms->nb_antenna_ports_eNB; aatx++) + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + avgs = cmax(avgs, avgP[(aarx << 1) + aatx]); + log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; +#ifdef UE_DEBUG_TRACE +LOG_D(PHY,"nr_tti_rx %d: pdcch log2_maxh = %d (%d,%d)\n",nr_tti_rx,log2_maxh,avgP[0],avgs); +#endif + +#if T_TRACER +T(T_UE_PHY_PDCCH_ENERGY, T_INT(eNB_id), T_INT(0), T_INT(frame%1024), T_INT(nr_tti_rx), + T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); +#endif + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh); + #endif + // compute LLRs for ofdm symbol 0 only + nr_pdcch_channel_compensation(pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_vars[eNB_id]->rxdataF_comp, + (aatx > 1) ? pdcch_vars[eNB_id]->rho : NULL, + frame_parms, + s, + log2_maxh, + coreset_nbr_rb); // log2_maxh+I0_shift + +/* +printf("\t### in nr_rx_pdcch() function we enter pdcch_channel_compensation(log2_maxh=%d) => compute LLRs for ofdm symbol 0 only, pdcch_vars[eNB_id]->rxdataF_ext ---> pdcch_vars[eNB_id]->rxdataF_comp\n",log2_maxh); + + // compute LLRs for ofdm symbol 0 only + pdcch_channel_compensation(pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_vars[eNB_id]->rxdataF_comp, + (aatx>1) ? pdcch_vars[eNB_id]->rho : NULL, + frame_parms, + 0, + log2_maxh);// log2_maxh+I0_shift +*/ + + +#ifdef DEBUG_PHY + + if (nr_tti_rx==5) + write_output("rxF_comp_d.m","rxF_c_d",&pdcch_vars[eNB_id]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + +#endif + +#ifdef MU_RECEIVER + + if (is_secondary_ue) { + //get MF output for interfering stream + pdcch_channel_compensation(pdcch_vars[eNB_id_i]->rxdataF_ext, + pdcch_vars[eNB_id_i]->dl_ch_estimates_ext, + pdcch_vars[eNB_id_i]->rxdataF_comp, + (aatx>1) ? pdcch_vars[eNB_id_i]->rho : NULL, + frame_parms, + 0, + log2_maxh);// log2_maxh+I0_shift +#ifdef DEBUG_PHY + write_output("rxF_comp_i.m","rxF_c_i",&pdcch_vars[eNB_id_i]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); +#endif + pdcch_dual_stream_correlation(frame_parms, + 0, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_vars[eNB_id_i]->dl_ch_estimates_ext, + pdcch_vars[eNB_id]->dl_ch_rho_ext, + log2_maxh); + } + +#endif //MU_RECEIVER + + if (frame_parms->nb_antennas_rx > 1) { +#ifdef MU_RECEIVER + + if (is_secondary_ue) { + pdcch_detection_mrc_i(frame_parms, + pdcch_vars[eNB_id]->rxdataF_comp, + pdcch_vars[eNB_id_i]->rxdataF_comp, + pdcch_vars[eNB_id]->rho, + pdcch_vars[eNB_id]->dl_ch_rho_ext, + 0); +#ifdef DEBUG_PHY + write_output("rxF_comp_d.m","rxF_c_d",&pdcch_vars[eNB_id]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_i.m","rxF_c_i",&pdcch_vars[eNB_id_i]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); +#endif + } else +#endif //MU_RECEIVER + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", + frame_parms->nb_antennas_rx); + #endif + pdcch_detection_mrc(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s); + } + if (mimo_mode == SISO) { + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_siso(for symbol 0) ---> pdcch_vars[eNB_id]->rxdataF_comp\n"); + #endif + pdcch_siso(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s); + } else pdcch_alamouti(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s); + +#ifdef MU_RECEIVER + + if (is_secondary_ue) { + pdcch_qpsk_qpsk_llr(frame_parms, + pdcch_vars[eNB_id]->rxdataF_comp, + pdcch_vars[eNB_id_i]->rxdataF_comp, + pdcch_vars[eNB_id]->dl_ch_rho_ext, + pdcch_vars[eNB_id]->llr16, //subsequent function require 16 bit llr, but output must be 8 bit (actually clipped to 4, because of the Viterbi decoder) + pdcch_vars[eNB_id]->llr, + 0); + /* + #ifdef DEBUG_PHY + if (subframe==5) { + write_output("llr8_seq.m","llr8",&pdcch_vars[eNB_id]->llr[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); + write_output("llr16_seq.m","llr16",&pdcch_vars[eNB_id]->llr16[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); + } + #endif*/ + } else { +#endif //MU_RECEIVER + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s); + #endif + nr_pdcch_llr(frame_parms, + pdcch_vars[eNB_id]->rxdataF_comp, + (char *) pdcch_vars[eNB_id]->llr, + s, + coreset_nbr_rb); + /* + printf("\t### in nr_rx_pdcch() function we enter pdcch_llr(for symbol 0), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n"); + pdcch_llr(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,(char *) pdcch_vars[eNB_id]->llr, 0); + */ + /*#ifdef DEBUG_PHY + write_output("llr8_seq.m","llr8",&pdcch_vars[eNB_id]->llr[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); + #endif*/ + +#ifdef MU_RECEIVER +} +#endif //MU_RECEIVER + +#if T_TRACER +T(T_UE_PHY_PDCCH_IQ, T_INT(frame_parms->N_RB_DL), T_INT(frame_parms->N_RB_DL), + T_INT(n_pdcch_symbols), + T_BUFFER(pdcch_vars[eNB_id]->rxdataF_comp, frame_parms->N_RB_DL*12*n_pdcch_symbols* 4)); +#endif + + /* We do not enter this function: in NR the number of PDCCH symbols is determined by higher layers parameter CORESET-time-dur + /*/ + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we do not enter function rx_pcfich()\n as the number of PDCCH symbols is determined by higher layers parameter CORESET-time-dur and n_pdcch_symbols=%d\n",n_pdcch_symbols); + /* + // decode pcfich here and find out pdcch ofdm symbol number + n_pdcch_symbols = rx_pcfich(frame_parms, nr_tti_rx, pdcch_vars[eNB_id],mimo_mode); + if (n_pdcch_symbols > 3) n_pdcch_symbols = 1; + */ +#ifdef DEBUG_DCI_DECODING + printf("demapping: nr_tti_rx %d, mi %d, tdd_config %d\n",nr_tti_rx,get_mi(frame_parms,nr_tti_rx),frame_parms->tdd_config); +#endif + + } + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_demapping()\n"); + #endif + nr_pdcch_demapping(pdcch_vars[eNB_id]->llr, + pdcch_vars[eNB_id]->wbar, + frame_parms, + coreset_time_dur, + coreset_nbr_rb); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_deinterleaving()\n"); + #endif + nr_pdcch_deinterleaving(frame_parms, + (uint16_t*) pdcch_vars[eNB_id]->e_rx, + pdcch_vars[eNB_id]->wbar, + coreset_time_dur, + reg_bundle_size_L, + coreset_interleaver_size_R, + n_shift, + coreset_nbr_rb); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_unscrambling()\n"); + #endif + nr_pdcch_unscrambling(pdcch_vars[eNB_id]->crnti, + frame_parms, + nr_tti_rx, + pdcch_vars[eNB_id]->e_rx, + coreset_time_dur*coreset_nbr_rb*9*2, + // get_nCCE(n_pdcch_symbols, frame_parms, mi) * 72, + pdcch_DMRS_scrambling_id, + do_common); +/* + printf("\t### in nr_rx_pdcch() function we enter pdcch_demapping()\n"); + + pdcch_demapping(pdcch_vars[eNB_id]->llr, + pdcch_vars[eNB_id]->wbar, + frame_parms, + n_pdcch_symbols, + get_mi(frame_parms,nr_tti_rx)); + + printf("\t### in nr_rx_pdcch() function we enter pdcch_deinterleaving()\n"); + + pdcch_deinterleaving(frame_parms, + (uint16_t*)pdcch_vars[eNB_id]->e_rx, + pdcch_vars[eNB_id]->wbar, + n_pdcch_symbols, + mi); + + printf("\t### in nr_rx_pdcch() function we enter pdcch_unscrambling()\n"); + + pdcch_unscrambling(frame_parms, + nr_tti_rx, + pdcch_vars[eNB_id]->e_rx, + get_nCCE(n_pdcch_symbols,frame_parms,mi)*72); +*/ + + pdcch_vars[eNB_id]->num_pdcch_symbols = n_pdcch_symbols; + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> Ending nr_rx_pdcch() function\n"); + #endif + return (0); +} +#endif + + + +void pdcch_scrambling(NR_DL_FRAME_PARMS *frame_parms, + uint8_t nr_tti_rx, + uint8_t *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 = (nr_tti_rx<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 + + 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; + } + + // printf("scrambling %d : e %d, c %d\n",i,e[i],((s>>(i&0x1f))&1)); + if (e[i] != 2) // <NIL> element is 2 + e[i] = (e[i]&1) ^ ((s>>(i&0x1f))&1); + } +} + + +#ifdef NR_PDCCH_DCI_RUN + +void nr_pdcch_unscrambling(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, + int8_t* llr, uint32_t length, uint16_t pdcch_DMRS_scrambling_id, int do_common) { + + int i; + uint8_t reset; + uint32_t x1, x2, s = 0; + uint16_t n_id; //{0,1,...,65535} + uint32_t n_rnti; + + reset = 1; + // x1 is set in first call to lte_gold_generic + //do_common=1; +if (do_common){ + n_id = frame_parms->Nid_cell; + n_rnti = 0; +} else { + n_id = pdcch_DMRS_scrambling_id; + n_rnti = (uint32_t)crnti; +} +//x2 = ((n_rnti * (1 << 16)) + n_id)%(1 << 31); +//uint32_t puissance_2_16 = ((1<<16)*n_rnti)+n_id; +//uint32_t puissance_2_31= (1<<30)*2; +//uint32_t calc_x2=puissance_2_16%puissance_2_31; + x2 = (((1<<16)*n_rnti)+n_id)%((1<<30)*2); //this is c_init in 38.211 v15.1.0 Section 7.3.2.3 +// x2 = (nr_tti_rx << 9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 +#ifdef NR_PDCCH_DCI_DEBUG +printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> (c_init=%d, n_id=%d, n_rnti=%d)\n",x2,n_id,n_rnti); +#endif + 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; + } + + // printf("unscrambling %d : e %d, c %d => ",i,llr[i],((s>>(i&0x1f))&1)); + if (((s >> (i % 32)) & 1) == 0) + llr[i] = -llr[i]; + // printf("%d\n",llr[i]); + + } +} + + +#endif + + + + +void pdcch_unscrambling(NR_DL_FRAME_PARMS *frame_parms, + uint8_t nr_tti_rx, + int8_t* llr, + uint32_t length) +{ + + int i; + uint8_t reset; + uint32_t x1, x2, s=0; + + reset = 1; + // x1 is set in first call to lte_gold_generic + + x2 = (nr_tti_rx<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 + + 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; + } + + + // printf("unscrambling %d : e %d, c %d => ",i,llr[i],((s>>(i&0x1f))&1)); + if (((s>>(i%32))&1)==0) + llr[i] = -llr[i]; + // printf("%d\n",llr[i]); + + } +} + + +/*uint8_t get_num_pdcch_symbols(uint8_t num_dci, + DCI_ALLOC_t *dci_alloc, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t nr_tti_rx) +{ + + uint16_t numCCE = 0; + uint8_t i; + uint8_t nCCEmin = 0; + uint16_t CCE_max_used_index = 0; + uint16_t firstCCE_max = dci_alloc[0].firstCCE; + uint8_t L = dci_alloc[0].L; + + // check pdcch duration imposed by PHICH duration (Section 6.9 of 36-211) + if (frame_parms->Ncp==1) { // extended prefix + if ((frame_parms->frame_type == TDD) && + ((frame_parms->tdd_config<3)||(frame_parms->tdd_config==6)) && + ((nr_tti_rx==1) || (nr_tti_rx==6))) // subframes 1 and 6 (S-subframes) for 5ms switching periodicity are 2 symbols + nCCEmin = 2; + else { // 10ms switching periodicity is always 3 symbols, any DL-only subframe is 3 symbols + nCCEmin = 3; + } + } + + // compute numCCE + for (i=0; i<num_dci; i++) { + // printf("dci %d => %d\n",i,dci_alloc[i].L); + numCCE += (1<<(dci_alloc[i].L)); + + if(firstCCE_max < dci_alloc[i].firstCCE) { + firstCCE_max = dci_alloc[i].firstCCE; + L = dci_alloc[i].L; + } + } + CCE_max_used_index = firstCCE_max + (1<<L) - 1; + + //if ((9*numCCE) <= (frame_parms->N_RB_DL*2)) + if (CCE_max_used_index < get_nCCE(1, frame_parms, get_mi(frame_parms, nr_tti_rx))) + return(cmax(1,nCCEmin)); + //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 4 : 5))) + else if (CCE_max_used_index < get_nCCE(2, frame_parms, get_mi(frame_parms, nr_tti_rx))) + return(cmax(2,nCCEmin)); + //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 7 : 8))) + else if (CCE_max_used_index < get_nCCE(3, frame_parms, get_mi(frame_parms, nr_tti_rx))) + return(cmax(3,nCCEmin)); + else if (frame_parms->N_RB_DL<=10) { + if (frame_parms->Ncp == 0) { // normal CP + printf("numCCE %d, N_RB_DL = %d : should be returning 4 PDCCH symbols (%d,%d,%d)\n",numCCE,frame_parms->N_RB_DL, + get_nCCE(1, frame_parms, get_mi(frame_parms, nr_tti_rx)), + get_nCCE(2, frame_parms, get_mi(frame_parms, nr_tti_rx)), + get_nCCE(3, frame_parms, get_mi(frame_parms, nr_tti_rx))); + + if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 10 : 11))) + return(4); + } else { // extended CP + if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 9 : 10))) + return(4); + } + } + + + LOG_D(PHY," dci.c: get_num_pdcch_symbols nr_tti_rx %d FATAL, illegal numCCE %d (num_dci %d)\n",nr_tti_rx,numCCE,num_dci); + //for (i=0;i<num_dci;i++) { + // printf("dci_alloc[%d].L = %d\n",i,dci_alloc[i].L); + //} + //exit(-1); + return(0); +} + +uint8_t generate_dci_top(int num_dci, + DCI_ALLOC_t *dci_alloc, + uint32_t n_rnti, + int16_t amp, + NR_DL_FRAME_PARMS *frame_parms, + int32_t **txdataF, + uint32_t nr_tti_rx) +{ + + uint8_t *e_ptr,num_pdcch_symbols; + uint32_t i, lprime; + uint32_t gain_lin_QPSK,kprime,kprime_mod12,mprime,nsymb,symbol_offset,tti_offset; + int16_t re_offset; + uint8_t mi = get_mi(frame_parms,nr_tti_rx); + static uint8_t e[DCI_BITS_MAX]; + static int32_t yseq0[Msymb],yseq1[Msymb],wbar0[Msymb],wbar1[Msymb]; + + int32_t *y[2]; + int32_t *wbar[2]; + + int nushiftmod3 = frame_parms->nushift%3; + + int Msymb2; + int split_flag=0; + + switch (frame_parms->N_RB_DL) { + case 100: + Msymb2 = Msymb; + break; + + case 75: + Msymb2 = 3*Msymb/4; + break; + + case 50: + Msymb2 = Msymb>>1; + break; + + case 25: + Msymb2 = Msymb>>2; + break; + + case 15: + Msymb2 = Msymb*15/100; + break; + + case 6: + Msymb2 = Msymb*6/100; + break; + + default: + Msymb2 = Msymb>>2; + break; + } + + num_pdcch_symbols = get_num_pdcch_symbols(num_dci,dci_alloc,frame_parms,nr_tti_rx); + // printf("nr_tti_rx %d in generate_dci_top num_pdcch_symbols = %d, num_dci %d\n", + // nr_tti_rx,num_pdcch_symbols,num_dci); + generate_pcfich(num_pdcch_symbols, + amp, + frame_parms, + txdataF, + nr_tti_rx); + wbar[0] = &wbar0[0]; + wbar[1] = &wbar1[0]; + y[0] = &yseq0[0]; + y[1] = &yseq1[0]; + + // reset all bits to <NIL>, here we set <NIL> elements as 2 + // memset(e, 2, DCI_BITS_MAX); + // here we interpret NIL as a random QPSK sequence. That makes power estimation easier. + for (i=0; i<DCI_BITS_MAX; i++) + e[i]=taus()&1; + + e_ptr = e; + + // generate DCIs + for (i=0; i<num_dci; i++) { +#ifdef DEBUG_DCI_ENCODING + printf("Generating %s DCI %d/%d (nCCE %d) of length %d, aggregation %d (%x)\n", + dci_alloc[i].search_space == DCI_COMMON_SPACE ? "common" : "UE", + i,num_dci,dci_alloc[i].firstCCE,dci_alloc[i].dci_length,1<<dci_alloc[i].L, + *(unsigned int*)dci_alloc[i].dci_pdu); + dump_dci(frame_parms,&dci_alloc[i]); +#endif + + if (dci_alloc[i].firstCCE>=0) { + e_ptr = generate_dci0(dci_alloc[i].dci_pdu, + e+(72*dci_alloc[i].firstCCE), + dci_alloc[i].dci_length, + dci_alloc[i].L, + dci_alloc[i].rnti); + } + } + + // Scrambling + // printf("pdcch scrambling\n"); + pdcch_scrambling(frame_parms, + nr_tti_rx, + e, + 8*get_nquad(num_pdcch_symbols, frame_parms, mi)); + //72*get_nCCE(num_pdcch_symbols,frame_parms,mi)); + + + + + // Now do modulation + if (frame_parms->mode1_flag==1) + gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15); + else + gain_lin_QPSK = amp/2; + + e_ptr = e; + +#ifdef DEBUG_DCI_ENCODING + printf(" PDCCH Modulation, Msymb %d, Msymb2 %d,gain_lin_QPSK %d\n",Msymb,Msymb2,gain_lin_QPSK); +#endif + + + if (frame_parms->mode1_flag) { //SISO + + + for (i=0; i<Msymb2; i++) { + + //((int16_t*)(&(y[0][i])))[0] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + //((int16_t*)(&(y[1][i])))[0] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + ((int16_t*)(&(y[0][i])))[0] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + ((int16_t*)(&(y[1][i])))[0] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + e_ptr++; + //((int16_t*)(&(y[0][i])))[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + //((int16_t*)(&(y[1][i])))[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + ((int16_t*)(&(y[0][i])))[1] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + ((int16_t*)(&(y[1][i])))[1] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + + e_ptr++; + } + } else { //ALAMOUTI + + + for (i=0; i<Msymb2; i+=2) { + +#ifdef DEBUG_DCI_ENCODING + printf(" PDCCH Modulation (TX diversity): REG %d\n",i>>2); +#endif + // first antenna position n -> x0 + ((int16_t*)&y[0][i])[0] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + e_ptr++; + ((int16_t*)&y[0][i])[1] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + e_ptr++; + + // second antenna position n -> -x1* + ((int16_t*)&y[1][i])[0] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? gain_lin_QPSK : -gain_lin_QPSK; + e_ptr++; + ((int16_t*)&y[1][i])[1] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + e_ptr++; + + // fill in the rest of the ALAMOUTI precoding + ((int16_t*)&y[0][i+1])[0] = -((int16_t*)&y[1][i])[0]; + ((int16_t*)&y[0][i+1])[1] = ((int16_t*)&y[1][i])[1]; + ((int16_t*)&y[1][i+1])[0] = ((int16_t*)&y[0][i])[0]; + ((int16_t*)&y[1][i+1])[1] = -((int16_t*)&y[0][i])[1]; + + } + } + + +#ifdef DEBUG_DCI_ENCODING + printf(" PDCCH Interleaving\n"); +#endif + + // printf("y %p (%p,%p), wbar %p (%p,%p)\n",y,y[0],y[1],wbar,wbar[0],wbar[1]); + // This is the interleaving procedure defined in 36-211, first part of Section 6.8.5 + pdcch_interleaving(frame_parms,&y[0],&wbar[0],num_pdcch_symbols,mi); + + mprime=0; + nsymb = (frame_parms->Ncp==0) ? 14:12; + re_offset = frame_parms->first_carrier_offset; + + // This is the REG allocation algorithm from 36-211, second part of Section 6.8.5 + // printf("DCI (SF %d) : txdataF %p (0 %p)\n",subframe,&txdataF[0][512*14*subframe],&txdataF[0][0]); + for (kprime=0; kprime<frame_parms->N_RB_DL*12; kprime++) { + for (lprime=0; lprime<num_pdcch_symbols; lprime++) { + + symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(lprime+(nr_tti_rx*nsymb)); + + + + tti_offset = symbol_offset + re_offset; + + (re_offset==(frame_parms->ofdm_symbol_size-2)) ? (split_flag=1) : (split_flag=0); + + // printf("kprime %d, lprime %d => REG %d (symbol %d)\n",kprime,lprime,(lprime==0)?(kprime/6) : (kprime>>2),symbol_offset); + // if REG is allocated to PHICH, skip it + if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) { +#ifdef DEBUG_DCI_ENCODING + printf("generate_dci: skipping REG %d (kprime %d, lprime %d)\n",(lprime==0)?(kprime/6) : (kprime>>2),kprime,lprime); +#endif + } else { + // Copy REG to TX buffer + + if ((lprime == 0)|| + ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4))) { + // first symbol, or second symbol+4 TX antennas skip pilots + + kprime_mod12 = kprime%12; + + if ((kprime_mod12 == 0) || (kprime_mod12 == 6)) { + // kprime represents REG + + for (i=0; i<6; i++) { + if ((i!=(nushiftmod3))&&(i!=(nushiftmod3+3))) { + txdataF[0][tti_offset+i] = wbar[0][mprime]; + + if (frame_parms->nb_antenna_ports_eNB > 1) + txdataF[1][tti_offset+i] = wbar[1][mprime]; + +#ifdef DEBUG_DCI_ENCODING + printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); +#endif + + mprime++; + } + } + } + } else { // no pilots in this symbol + kprime_mod12 = kprime%12; + + if ((kprime_mod12 == 0) || (kprime_mod12 == 4) || (kprime_mod12 == 8)) { + // kprime represents REG + if (split_flag==0) { + for (i=0; i<4; i++) { + txdataF[0][tti_offset+i] = wbar[0][mprime]; + + if (frame_parms->nb_antenna_ports_eNB > 1) + txdataF[1][tti_offset+i] = wbar[1][mprime]; + +#ifdef DEBUG_DCI_ENCODING + LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); +#endif + mprime++; + } + } else { + txdataF[0][tti_offset+0] = wbar[0][mprime]; + + if (frame_parms->nb_antenna_ports_eNB > 1) + txdataF[1][tti_offset+0] = wbar[1][mprime]; + +#ifdef DEBUG_DCI_ENCODING + printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); +#endif + mprime++; + txdataF[0][tti_offset+1] = wbar[0][mprime]; + + if (frame_parms->nb_antenna_ports_eNB > 1) + txdataF[1][tti_offset+1] = wbar[1][mprime]; + +#ifdef DEBUG_DCI_ENCODING + printf("PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+1,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); +#endif + mprime++; + txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[0][mprime]; + + if (frame_parms->nb_antenna_ports_eNB > 1) + txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[1][mprime]; + +#ifdef DEBUG_DCI_ENCODING + printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset-frame_parms->ofdm_symbol_size+3,*(short*)&wbar[0][mprime], + *(1+(short*)&wbar[0][mprime])); +#endif + mprime++; + txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[0][mprime]; + + if (frame_parms->nb_antenna_ports_eNB > 1) + txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[1][mprime]; + +#ifdef DEBUG_DCI_ENCODING + printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset-frame_parms->ofdm_symbol_size+4,*(short*)&wbar[0][mprime], + *(1+(short*)&wbar[0][mprime])); +#endif + mprime++; + + } + } + } + + if (mprime>=Msymb2) + return(num_pdcch_symbols); + } // check_phich_reg + + } //lprime loop + + re_offset++; + + if (re_offset == (frame_parms->ofdm_symbol_size)) + re_offset = 1; + } // kprime loop + + return(num_pdcch_symbols); +} +*/ +#ifdef PHY_ABSTRACTION +uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB, + int num_dci, + DCI_ALLOC_t *dci_alloc, + uint8_t subframe) +{ + int n_dci, n_dci_dl; + uint8_t ue_id; + LTE_eNB_DLSCH_t *dlsch_eNB; + int num_ue_spec_dci; + int num_common_dci; + int i; + uint8_t num_pdcch_symbols = get_num_pdcch_symbols(num_dci, + dci_alloc, + &phy_vars_eNB->frame_parms, + subframe); + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].cntl.cfi=num_pdcch_symbols; + + num_ue_spec_dci = 0; + num_common_dci = 0; + for (i = 0; i < num_dci; i++) { + /* TODO: maybe useless test, to remove? */ + if (!(dci_alloc[i].firstCCE>=0)) abort(); + if (dci_alloc[i].search_space == DCI_COMMON_SPACE) + num_common_dci++; + else + num_ue_spec_dci++; + } + + memcpy(phy_vars_eNB->dci_alloc[subframe&1],dci_alloc,sizeof(DCI_ALLOC_t)*(num_dci)); + phy_vars_eNB->num_ue_spec_dci[subframe&1]=num_ue_spec_dci; + phy_vars_eNB->num_common_dci[subframe&1]=num_common_dci; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_ue_spec_dci = num_ue_spec_dci; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_common_dci = num_common_dci; + + LOG_D(PHY,"[eNB %d][DCI][EMUL] CC id %d: num spec dci %d num comm dci %d num PMCH %d \n", + phy_vars_eNB->Mod_id, phy_vars_eNB->CC_id, num_ue_spec_dci,num_common_dci, + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_pmch); + + if (eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].cntl.pmch_flag == 1 ) + n_dci_dl = eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_pmch; + else + n_dci_dl = 0; + + for (n_dci =0 ; + n_dci < (eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_ue_spec_dci+ eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_common_dci); + n_dci++) { + + if (dci_alloc[n_dci].format > 0) { // exclude the uplink dci + + if (dci_alloc[n_dci].rnti == SI_RNTI) { + dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_SI; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 0;//SI; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = 0; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[0]->TBS>>3; + LOG_D(PHY,"[DCI][EMUL]SI tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl],n_dci_dl, + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl]); + } else if (dci_alloc[n_dci_dl].ra_flag == 1) { + dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_ra; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 1;//RA; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = 0; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[0]->TBS>>3; + LOG_D(PHY,"[DCI][EMUL] RA tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl],n_dci_dl, + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl]); + } else { + ue_id = find_ue(dci_alloc[n_dci_dl].rnti,PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]); + DevAssert( ue_id != (uint8_t)-1 ); + dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch[ue_id][0]; + + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 2;//TB0; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = dlsch_eNB->current_harq_pid; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].ue_id[n_dci_dl] = ue_id; + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[dlsch_eNB->current_harq_pid]->TBS>>3; + LOG_D(PHY,"[DCI][EMUL] TB1 tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl],n_dci_dl, + eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl]); + // check for TB1 later + + } + } + + n_dci_dl++; + } + + memcpy((void *)&eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dci_alloc, + (void *)dci_alloc, + n_dci*sizeof(DCI_ALLOC_t)); + + return(num_pdcch_symbols); +} +#endif + + +void dci_decoding(uint8_t DCI_LENGTH, + uint8_t aggregation_level, + int8_t *e, + uint8_t *decoded_output) +{ + + uint8_t dummy_w_rx[3*(MAX_DCI_SIZE_BITS+16+64)]; + int8_t w_rx[3*(MAX_DCI_SIZE_BITS+16+32)],d_rx[96+(3*(MAX_DCI_SIZE_BITS+16))]; + + uint16_t RCC; + + uint16_t D=(DCI_LENGTH+16+64); + uint16_t coded_bits; +#ifdef DEBUG_DCI_DECODING + int32_t i; +#endif + + if (aggregation_level>3) { + LOG_I(PHY," dci.c: dci_decoding FATAL, illegal aggregation_level %d\n",aggregation_level); + return; + } + + coded_bits = 72 * (1<<aggregation_level); + +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY," Doing DCI decoding for %d bits, DCI_LENGTH %d,coded_bits %d, e %p\n",3*(DCI_LENGTH+16),DCI_LENGTH,coded_bits,e); +#endif + + // now do decoding + memset((void*)dummy_w_rx,0,3*D); + RCC = generate_dummy_w_cc(DCI_LENGTH+16, + dummy_w_rx); + + + +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY," Doing DCI Rate Matching RCC %d, w %p\n",RCC,w); +#endif + + lte_rate_matching_cc_rx(RCC,coded_bits,w_rx,dummy_w_rx,e); + + sub_block_deinterleaving_cc((uint32_t)(DCI_LENGTH+16), + &d_rx[96], + &w_rx[0]); + +#ifdef DEBUG_DCI_DECODING + + for (i=0; i<16+DCI_LENGTH; i++) + LOG_I(PHY," DCI %d : (%d,%d,%d)\n",i,*(d_rx+96+(3*i)),*(d_rx+97+(3*i)),*(d_rx+98+(3*i))); + +#endif + memset(decoded_output,0,2+((16+DCI_LENGTH)>>3)); + +#ifdef DEBUG_DCI_DECODING + printf("Before Viterbi\n"); + + for (i=0; i<16+DCI_LENGTH; i++) + printf("%d : (%d,%d,%d)\n",i,*(d_rx+96+(3*i)),*(d_rx+97+(3*i)),*(d_rx+98+(3*i))); + +#endif + //debug_printf("Doing DCI Viterbi \n"); + phy_viterbi_lte_sse2(d_rx+96,decoded_output,16+DCI_LENGTH); + //debug_printf("Done DCI Viterbi \n"); +} + + +static uint8_t dci_decoded_output[RX_NB_TH][(MAX_DCI_SIZE_BITS+64)/8]; + +/*uint16_t get_nCCE(uint8_t num_pdcch_symbols,NR_DL_FRAME_PARMS *frame_parms,uint8_t mi) +{ + return(get_nquad(num_pdcch_symbols,frame_parms,mi)/9); +} + +uint16_t get_nquad(uint8_t num_pdcch_symbols,NR_DL_FRAME_PARMS *frame_parms,uint8_t mi) +{ + + uint16_t Nreg=0; + uint8_t Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48; + + if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0) + Ngroup_PHICH++; + + if (frame_parms->Ncp == 1) { + Ngroup_PHICH<<=1; + } + + Ngroup_PHICH*=mi; + + if ((num_pdcch_symbols>0) && (num_pdcch_symbols<4)) + switch (frame_parms->N_RB_DL) { + case 6: + Nreg=12+(num_pdcch_symbols-1)*18; + break; + + case 25: + Nreg=50+(num_pdcch_symbols-1)*75; + break; + + case 50: + Nreg=100+(num_pdcch_symbols-1)*150; + break; + + case 100: + Nreg=200+(num_pdcch_symbols-1)*300; + break; + + default: + return(0); + } + + // printf("Nreg %d (%d)\n",Nreg,Nreg - 4 - (3*Ngroup_PHICH)); + return(Nreg - 4 - (3*Ngroup_PHICH)); +} + +uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int nr_tti_rx) +{ + + // check for eNB only ! + return(get_nCCE(num_pdcch_symbols, + &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms, + get_mi(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,nr_tti_rx))); +} +*/ + +int get_nCCE_offset_l1(int *CCE_table, + const unsigned char L, + const int nCCE, + const int common_dci, + const unsigned short rnti, + const unsigned char nr_tti_rx) +{ + + int search_space_free,m,nb_candidates = 0,l,i; + unsigned int Yk; + /* + printf("CCE Allocation: "); + for (i=0;i<nCCE;i++) + printf("%d.",CCE_table[i]); + printf("\n"); + */ + if (common_dci == 1) { + // check CCE(0 ... L-1) + nb_candidates = (L==4) ? 4 : 2; + nb_candidates = min(nb_candidates,nCCE/L); + + // printf("Common DCI nb_candidates %d, L %d\n",nb_candidates,L); + + for (m = nb_candidates-1 ; m >=0 ; m--) { + + search_space_free = 1; + for (l=0; l<L; l++) { + + // printf("CCE_table[%d] %d\n",(m*L)+l,CCE_table[(m*L)+l]); + if (CCE_table[(m*L) + l] == 1) { + search_space_free = 0; + break; + } + } + + if (search_space_free == 1) { + + // printf("returning %d\n",m*L); + + for (l=0; l<L; l++) + CCE_table[(m*L)+l]=1; + return(m*L); + } + } + + return(-1); + + } else { // Find first available in ue specific search space + // according to procedure in Section 9.1.1 of 36.213 (v. 8.6) + // compute Yk + Yk = (unsigned int)rnti; + + for (i=0; i<=nr_tti_rx; i++) + Yk = (Yk*39827)%65537; + + Yk = Yk % (nCCE/L); + + + switch (L) { + case 1: + case 2: + nb_candidates = 6; + break; + + case 4: + case 8: + nb_candidates = 2; + break; + + default: + DevParam(L, nCCE, rnti); + break; + } + + + LOG_D(MAC,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates); + + for (m = 0 ; m < nb_candidates ; m++) { + search_space_free = 1; + + for (l=0; l<L; l++) { + int cce = (((Yk+m)%(nCCE/L))*L) + l; + if (cce >= nCCE || CCE_table[cce] == 1) { + search_space_free = 0; + break; + } + } + + if (search_space_free == 1) { + for (l=0; l<L; l++) + CCE_table[(((Yk+m)%(nCCE/L))*L)+l]=1; + + return(((Yk+m)%(nCCE/L))*L); + } + } + + return(-1); + } +} + + + + +#ifdef NR_PDCCH_DCI_RUN +void nr_dci_decoding_procedure0(int s, + int p, + NR_UE_PDCCH **pdcch_vars, + int do_common, + //dci_detect_mode_t mode, + uint8_t nr_tti_rx, + NR_DCI_ALLOC_t *dci_alloc, + // uint8_t nr_tti_rx, NR_DCI_ALLOC_t *dci_alloc, + int16_t eNB_id, + uint8_t current_thread_id, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t mi, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint16_t tc_rnti, + uint16_t int_rnti, + uint16_t sfi_rnti, + uint16_t tpc_pusch_rnti, + uint16_t tpc_pucch_rnti, + uint16_t tpc_srs_rnti, + uint8_t L, + uint8_t format_si, + uint8_t format_p, + uint8_t format_ra, + uint8_t format_c, + uint8_t sizeof_bits, + uint8_t sizeof_bytes, + uint8_t *dci_cnt, + uint8_t *format0_found, + uint8_t *format_c_found, + uint32_t *CCEmap0, + uint32_t *CCEmap1, + uint32_t *CCEmap2) { + + uint16_t crc, CCEind, nCCE[3]; + uint32_t *CCEmap = NULL, CCEmap_mask = 0; + int L2 = (1 << L); + unsigned int Yk, nb_candidates = 0, i, m; + unsigned int CCEmap_cand; + + // A[p], p is the current active CORESET + uint16_t A[3]={39827,39829,39839}; + //Table 10.1-2: Maximum number of PDCCH candidates per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3} + uint8_t m_max_slot_pdcch_Table10_1_2 [4] = {44,36,22,20}; + //Table 10.1-3: Maximum number of non-overlapped CCEs per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3} + uint8_t cce_max_slot_pdcch_Table10_1_3 [4] = {56,56,48,32}; + + int coreset_nbr_cce_per_symbol=0; + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> \n"); + #endif + +// if (mode == NO_DCI) { +// #ifdef NR_PDCCH_DCI_DEBUG +// printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> skip DCI decoding: expect no DCIs at nr_tti_rx %d in current searchSpace\n", nr_tti_rx); +// #endif +// return; +// } + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> frequencyDomainResources=%llx, duration=%d\n", + pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources, pdcch_vars[eNB_id]->coreset[p].duration); + #endif + + // nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols, frame_parms, mi); + for (int i = 0; i < 45; i++) { + // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' + if (((pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_cce_per_symbol++; + } + nCCE[p] = pdcch_vars[eNB_id]->coreset[p].duration*coreset_nbr_cce_per_symbol; // 1 CCE = 6 RB + // p is the current CORESET we are currently monitoring (among the 3 possible CORESETs in a BWP) + // the number of CCE in the current CORESET is: + // the number of symbols in the CORESET (pdcch_vars[eNB_id]->coreset[p].duration) + // multiplied by the number of bits set to '1' in the frequencyDomainResources bitmap + // (1 bit set to '1' corresponds to 6 RB and 1 CCE = 6 RB) + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> nCCE[%d]=%d\n",p,nCCE[p]); + #endif + +/* if (nCCE > get_nCCE(3, frame_parms, 1)) { + LOG_D(PHY, + "skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", + nCCE, get_nCCE(3, frame_parms, 1)); + return; + } + + if (nCCE < L2) { + LOG_D(PHY, "skip DCI decoding: nCCE=%d < L2=%d\n", nCCE, L2); + return; + } + + if (mode == NO_DCI) { + LOG_D(PHY, "skip DCI decoding: expect no DCIs at nr_tti_rx %d\n", + nr_tti_rx); + return; + } +*/ + if (do_common == 1) { + Yk = 0; + if (pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.common_dci_formats == cformat2_0) { + // for dci_format_2_0, the nb_candidates is obtained from a different variable + switch (L2) { + case 1: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel1; + break; + case 2: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel2; + break; + case 4: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel4; + break; + case 8: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel8; + break; + case 16: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel16; + break; + default: + break; + } + } else if (pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.common_dci_formats == cformat2_3) { + // for dci_format_2_3, the nb_candidates is obtained from a different variable + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.srs_nrofCandidates; + } else { + nb_candidates = (L2 == 4) ? 4 : ((L2 == 8)? 2 : 1); // according to Table 10.1-1 (38.213 section 10.1) + } + } else { + switch (L2) { + case 1: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel1; + break; + case 2: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel2; + break; + case 4: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel4; + break; + case 8: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel8; + break; + case 16: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel16; + break; + default: + break; + } + // Find first available in ue specific search space + // according to procedure in Section 10.1 of 38.213 + // compute Yk + Yk = (unsigned int) pdcch_vars[eNB_id]->crnti; + for (i = 0; i <= nr_tti_rx; i++) + Yk = (Yk * A[p]) % 65537; + } + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> L2(%d) | nCCE[%d](%d) | Yk(%d) | nb_candidates(%d)\n",L2,p,nCCE[p],Yk,nb_candidates); + #endif + /* for (CCEind=0; + CCEind<nCCE2; + CCEind+=(1<<L)) {*/ +// if (nb_candidates * L2 > nCCE[p]) +// nb_candidates = nCCE[p] / L2; + +// In the next code line there is maybe a bug. The spec is not comparing Table 10.1-2 with nb_candidates, but with total number of candidates for all s and all p + int m_p_s_L_max = (m_max_slot_pdcch_Table10_1_2[L]<=nb_candidates ? m_max_slot_pdcch_Table10_1_2[L] : nb_candidates); + if (L==4) m_p_s_L_max=1; // Table 10.1-2 is not defined for L=4 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> m_max_slot_pdcch_Table10_1_2(%d)=%d\n",L,m_max_slot_pdcch_Table10_1_2[L]); + #endif + for (m = 0; m < nb_candidates; m++) { + int n_ci = 0; + int debug1 = nCCE[p] / L2; + int debug2 = L2*m_p_s_L_max; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> debug1(%d)=nCCE[p]/L2 | nCCE[%d](%d) | L2(%d)\n",debug1,p,nCCE[p],L2); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> debug2(%d)=L2*m_p_s_L_max | L2(%d) | m_p_s_L_max(%d)\n",debug2,L2,m_p_s_L_max); + #endif + CCEind = (((Yk + ((m*nCCE[p])/(L2*m_p_s_L_max)) + n_ci) % (nCCE[p] / L2)) * L2); + #ifdef NR_PDCCH_DCI_DEBUG + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> CCEind(%d) = (((Yk(%d) + ((m(%d)*nCCE[p](%d))/(L2(%d)*m_p_s_L_max(%d)))) % (nCCE[p] / L2)) * L2)\n", + CCEind,Yk,m,nCCE[p],L2,m_p_s_L_max); + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> n_candidate(m)=%d | CCEind=%d |",m,CCEind); + #endif + if (CCEind < 32) + CCEmap = CCEmap0; + else if (CCEind < 64) + CCEmap = CCEmap1; + else if (CCEind < 96) + CCEmap = CCEmap2; + else { + LOG_E(PHY, "Illegal CCEind %d (Yk %d, m %d, nCCE %d, L2 %d\n",CCEind, Yk, m, nCCE, L2); + //mac_xface->macphy_exit("Illegal CCEind\n"); + return; // not reached + } + + switch (L2) { + case 1: + CCEmap_mask = (1 << (CCEind & 0x1f)); + break; + case 2: + CCEmap_mask = (3 << (CCEind & 0x1f)); + break; + case 4: + CCEmap_mask = (0xf << (CCEind & 0x1f)); + break; + case 8: + CCEmap_mask = (0xff << (CCEind & 0x1f)); + break; + case 16: + CCEmap_mask = (0xfff << (CCEind & 0x1f)); + break; + default: + LOG_E(PHY, "Illegal L2 value %d\n", L2); + //mac_xface->macphy_exit("Illegal L2\n"); + return; // not reached + } + CCEmap_cand = (*CCEmap) & CCEmap_mask; + // CCE is not allocated yet + #ifdef NR_PDCCH_DCI_DEBUG + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> CCEmap_cand=%d \n",CCEmap_cand); + #endif + + if (CCEmap_cand == 0) { + #ifdef DEBUG_DCI_DECODING + if (do_common == 1) + LOG_I(PHY,"[DCI search nPdcch %d - common] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n", + pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); + else + LOG_I(PHY,"[DCI search nPdcch %d - ue spec] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x) format %d\n", + pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_c); + #endif + #ifdef NR_PDCCH_DCI_DEBUG + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we enter function dci_decoding(sizeof_bits=%d L=%d) -----\n",sizeof_bits,L); + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we have to replace this part of the code by polar decoding\n"); + #endif + dci_decoding(sizeof_bits, L, &pdcch_vars[eNB_id]->e_rx[CCEind * 72], &dci_decoded_output[current_thread_id][0]); + /* + for (i=0;i<3+(sizeof_bits>>3);i++) + printf("dci_decoded_output[%d] => %x\n",i,dci_decoded_output[i]); + */ + crc = (crc16(&dci_decoded_output[current_thread_id][0], sizeof_bits) >> 16) ^ extract_crc(&dci_decoded_output[current_thread_id][0], sizeof_bits); + #ifdef NR_PDCCH_DCI_DEBUG + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we end function dci_decoding() with crc=%d\n",crc); + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we have to replace this part of the code by polar decoding\n"); + #endif + #ifdef DEBUG_DCI_DECODING + printf("crc =>%x\n",crc); + #endif //uint16_t tc_rnti, uint16_t int_rnti, uint16_t sfi_rnti, uint16_t tpc_pusch_rnti, uint16_t tpc_pucch_rnti, uint16_t tpc_srs__rnti + + if ((crc == si_rnti) || (crc == p_rnti) || (crc == ra_rnti) || (crc == tc_rnti) + || (crc == int_rnti) || (crc == sfi_rnti) || (crc == tpc_pusch_rnti) || (crc == tpc_pucch_rnti) || (crc == tpc_srs_rnti) + || (crc == pdcch_vars[eNB_id]->crnti)) { +/* if (((L > 1) && ((crc == si_rnti) || (crc == p_rnti) || (crc == ra_rnti))) + || (crc == pdcch_vars[eNB_id]->crnti)) {*/ + #ifdef NR_PDCCH_DCI_DEBUG + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> rnti matches -> DCI FOUND !!! crc =>%x, sizeof_bits %d, sizeof_bytes %d \n",crc, sizeof_bits, sizeof_bytes); + #endif + dci_alloc[*dci_cnt].dci_length = sizeof_bits; + dci_alloc[*dci_cnt].rnti = crc; + dci_alloc[*dci_cnt].L = L; + dci_alloc[*dci_cnt].firstCCE = CCEind; + if (sizeof_bytes <= 4) { + dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[current_thread_id][0]; + dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[current_thread_id][1]; + dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[current_thread_id][2]; + dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[current_thread_id][3]; +#ifdef DEBUG_DCI_DECODING + printf("DCI => %x,%x,%x,%x\n",dci_decoded_output[current_thread_id][0], + dci_decoded_output[current_thread_id][1], + dci_decoded_output[current_thread_id][2], + dci_decoded_output[current_thread_id][3]); +#endif + } else { + dci_alloc[*dci_cnt].dci_pdu[7] = dci_decoded_output[current_thread_id][0]; + dci_alloc[*dci_cnt].dci_pdu[6] = dci_decoded_output[current_thread_id][1]; + dci_alloc[*dci_cnt].dci_pdu[5] = dci_decoded_output[current_thread_id][2]; + dci_alloc[*dci_cnt].dci_pdu[4] = dci_decoded_output[current_thread_id][3]; + dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[current_thread_id][4]; + dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[current_thread_id][5]; + dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[current_thread_id][7]; + // format2_0, format2_1 can be longer than 8 bytes. FIXME +#ifdef DEBUG_DCI_DECODING + printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n", + dci_decoded_output[current_thread_id][0],dci_decoded_output[current_thread_id][1],dci_decoded_output[current_thread_id][2],dci_decoded_output[current_thread_id][3], + dci_decoded_output[current_thread_id][4],dci_decoded_output[current_thread_id][5],dci_decoded_output[current_thread_id][6],dci_decoded_output[current_thread_id][7]); +#endif + } + if (crc == si_rnti) { + dci_alloc[*dci_cnt].format = format1_0; + *dci_cnt = *dci_cnt + 1; + } else if (crc == p_rnti) { + dci_alloc[*dci_cnt].format = format1_0; + *dci_cnt = *dci_cnt + 1; + } else if (crc == ra_rnti) { + dci_alloc[*dci_cnt].format = format1_0; + *dci_cnt = *dci_cnt + 1; + } else if (crc == tc_rnti) { + dci_alloc[*dci_cnt].format = cformat0_0_and_1_0; // this tc-rnti scrambled crc can contain formats 0_0 or 0_1. FIXME + *dci_cnt = *dci_cnt + 1; + } else if (crc == int_rnti) { + dci_alloc[*dci_cnt].format = format2_1; + *dci_cnt = *dci_cnt + 1; + } else if (crc == sfi_rnti) { + dci_alloc[*dci_cnt].format = format2_0; + *dci_cnt = *dci_cnt + 1; + } else if (crc == tpc_pusch_rnti) { + dci_alloc[*dci_cnt].format = format2_2; + *dci_cnt = *dci_cnt + 1; + } else if (crc == tpc_pucch_rnti) { + dci_alloc[*dci_cnt].format = format2_2; + *dci_cnt = *dci_cnt + 1; + } else if (crc == tpc_srs_rnti) { + dci_alloc[*dci_cnt].format = format2_3; + *dci_cnt = *dci_cnt + 1; + } else if (crc == pdcch_vars[eNB_id]->crnti) { + dci_alloc[*dci_cnt].format = uformat0_0_and_1_0; // or uformat0_1_and_1_1. FIXME + *dci_cnt = *dci_cnt + 1; + } +/* if (crc == si_rnti) { + dci_alloc[*dci_cnt].format = format_si; + *dci_cnt = *dci_cnt + 1; + } else if (crc == p_rnti) { + dci_alloc[*dci_cnt].format = format_p; + *dci_cnt = *dci_cnt + 1; + } else if (crc == ra_rnti) { + dci_alloc[*dci_cnt].format = format_ra; + // store first nCCE of group for PUCCH transmission of ACK/NAK + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + *dci_cnt = *dci_cnt + 1; + } else if (crc == pdcch_vars[eNB_id]->crnti) { + + if ((mode & UL_DCI) && (format_c == format0) + && ((dci_decoded_output[current_thread_id][0] & 0x80) + == 0)) { // check if pdu is format 0 or 1A + if (*format0_found == 0) { + dci_alloc[*dci_cnt].format = format0; + *format0_found = 1; + *dci_cnt = *dci_cnt + 1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + } + } else if (format_c == format0) { // this is a format 1A DCI + dci_alloc[*dci_cnt].format = format1A; + *dci_cnt = *dci_cnt + 1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + } else { + // store first nCCE of group for PUCCH transmission of ACK/NAK + if (*format_c_found == 0) { + dci_alloc[*dci_cnt].format = format_c; + *dci_cnt = *dci_cnt + 1; + *format_c_found = 1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + } + } + }*/ + //LOG_I(PHY,"DCI decoding CRNTI [format: %d, nCCE[nr_tti_rx: %d]: %d ], AggregationLevel %d \n",format_c, nr_tti_rx, pdcch_vars[eNB_id]->nCCE[nr_tti_rx],L2); + // memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes); + switch (1 << L) { + case 1: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + case 2: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + case 4: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + case 8: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + case 16: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + } + +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY,"[DCI search] Found DCI %d rnti %x Aggregation %d length %d format %s in CCE %d (CCEmap %x) candidate %d / %d \n", + *dci_cnt,crc,1<<L,sizeof_bits,dci_format_strings[dci_alloc[*dci_cnt-1].format],CCEind,*CCEmap,m,nb_candidates ); + dump_dci(frame_parms,&dci_alloc[*dci_cnt-1]); + +#endif + return; + } // rnti match + } else { // CCEmap_cand == 0 + printf("\n"); + } +/* + if ( agregationLevel != 0xFF && + (format_c == format0 && m==0 && si_rnti != SI_RNTI)) + { + //Only valid for OAI : Save some processing time when looking for DCI format0. From the log we see the DCI only on candidate 0. + return; + } + */ + } // candidate loop + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> end candidate loop\n"); + #endif +} + +#endif + + + + +/*void dci_decoding_procedure0(NR_UE_PDCCH **pdcch_vars, + int do_common, + dci_detect_mode_t mode, + uint8_t nr_tti_rx, + DCI_ALLOC_t *dci_alloc, + int16_t eNB_id, + uint8_t current_thread_id, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t mi, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint8_t L, + uint8_t format_si, + uint8_t format_p, + uint8_t format_ra, + uint8_t format_c, + uint8_t sizeof_bits, + uint8_t sizeof_bytes, + uint8_t *dci_cnt, + uint8_t *format0_found, + uint8_t *format_c_found, + uint32_t *CCEmap0, + uint32_t *CCEmap1, + uint32_t *CCEmap2) +{ + + uint16_t crc,CCEind,nCCE; + uint32_t *CCEmap=NULL,CCEmap_mask=0; + int L2=(1<<L); + unsigned int Yk,nb_candidates = 0,i,m; + unsigned int CCEmap_cand; +#ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (dci_decoding_procedure0)-> \n"); +#endif + nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols,frame_parms,mi); + + if (nCCE > get_nCCE(3,frame_parms,1)) { + LOG_D(PHY,"skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", nCCE, get_nCCE(3,frame_parms,1)); + return; + } + + if (nCCE<L2) { + LOG_D(PHY,"skip DCI decoding: nCCE=%d < L2=%d\n", nCCE, L2); + return; + } + + if (mode == NO_DCI) { + LOG_D(PHY, "skip DCI decoding: expect no DCIs at nr_tti_rx %d\n", nr_tti_rx); + return; + } + + if (do_common == 1) { + nb_candidates = (L2==4) ? 4 : 2; + Yk=0; + } else { + // Find first available in ue specific search space + // according to procedure in Section 9.1.1 of 36.213 (v. 8.6) + // compute Yk + Yk = (unsigned int)pdcch_vars[eNB_id]->crnti; + + for (i=0; i<=nr_tti_rx; i++) + Yk = (Yk*39827)%65537; + + Yk = Yk % (nCCE/L2); + + switch (L2) { + case 1: + case 2: + nb_candidates = 6; + break; + + case 4: + case 8: + nb_candidates = 2; + break; + + default: + DevParam(L2, do_common, eNB_id); + break; + } + } + + // for (CCEind=0; + // CCEind<nCCE2; + // CCEind+=(1<<L)) { + + if (nb_candidates*L2 > nCCE) + nb_candidates = nCCE/L2; + + for (m=0; m<nb_candidates; m++) { + + CCEind = (((Yk+m)%(nCCE/L2))*L2); + + if (CCEind<32) + CCEmap = CCEmap0; + else if (CCEind<64) + CCEmap = CCEmap1; + else if (CCEind<96) + CCEmap = CCEmap2; + else { + LOG_E(PHY,"Illegal CCEind %d (Yk %d, m %d, nCCE %d, L2 %d\n",CCEind,Yk,m,nCCE,L2); + mac_xface->macphy_exit("Illegal CCEind\n"); + return; // not reached + } + + switch (L2) { + case 1: + CCEmap_mask = (1<<(CCEind&0x1f)); + break; + + case 2: + CCEmap_mask = (3<<(CCEind&0x1f)); + break; + + case 4: + CCEmap_mask = (0xf<<(CCEind&0x1f)); + break; + + case 8: + CCEmap_mask = (0xff<<(CCEind&0x1f)); + break; + + default: + LOG_E( PHY, "Illegal L2 value %d\n", L2 ); + mac_xface->macphy_exit( "Illegal L2\n" ); + return; // not reached + } + + CCEmap_cand = (*CCEmap)&CCEmap_mask; + + // CCE is not allocated yet + + if (CCEmap_cand == 0) { +#ifdef DEBUG_DCI_DECODING + + if (do_common == 1) + LOG_I(PHY,"[DCI search nPdcch %d - common] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n", + pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); + else + LOG_I(PHY,"[DCI search nPdcch %d - ue spec] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x) format %d\n", + pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_c); + +#endif + + dci_decoding(sizeof_bits, + L, + &pdcch_vars[eNB_id]->e_rx[CCEind*72], + &dci_decoded_output[current_thread_id][0]); + + // for (i=0;i<3+(sizeof_bits>>3);i++) + // printf("dci_decoded_output[%d] => %x\n",i,dci_decoded_output[i]); + + crc = (crc16(&dci_decoded_output[current_thread_id][0],sizeof_bits)>>16) ^ extract_crc(&dci_decoded_output[current_thread_id][0],sizeof_bits); +#ifdef DEBUG_DCI_DECODING + printf("crc =>%x\n",crc); +#endif + + if (((L>1) && ((crc == si_rnti)|| (crc == p_rnti)|| (crc == ra_rnti)))|| + (crc == pdcch_vars[eNB_id]->crnti)) { + dci_alloc[*dci_cnt].dci_length = sizeof_bits; + dci_alloc[*dci_cnt].rnti = crc; + dci_alloc[*dci_cnt].L = L; + dci_alloc[*dci_cnt].firstCCE = CCEind; + + //printf("DCI FOUND !!! crc =>%x, sizeof_bits %d, sizeof_bytes %d \n",crc, sizeof_bits, sizeof_bytes); + if (sizeof_bytes<=4) { + dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[current_thread_id][0]; + dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[current_thread_id][1]; + dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[current_thread_id][2]; + dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[current_thread_id][3]; +#ifdef DEBUG_DCI_DECODING + printf("DCI => %x,%x,%x,%x\n",dci_decoded_output[current_thread_id][0], + dci_decoded_output[current_thread_id][1], + dci_decoded_output[current_thread_id][2], + dci_decoded_output[current_thread_id][3]); +#endif + } else { + dci_alloc[*dci_cnt].dci_pdu[7] = dci_decoded_output[current_thread_id][0]; + dci_alloc[*dci_cnt].dci_pdu[6] = dci_decoded_output[current_thread_id][1]; + dci_alloc[*dci_cnt].dci_pdu[5] = dci_decoded_output[current_thread_id][2]; + dci_alloc[*dci_cnt].dci_pdu[4] = dci_decoded_output[current_thread_id][3]; + dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[current_thread_id][4]; + dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[current_thread_id][5]; + dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[current_thread_id][6]; + dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[current_thread_id][7]; +#ifdef DEBUG_DCI_DECODING + printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n", + dci_decoded_output[current_thread_id][0],dci_decoded_output[current_thread_id][1],dci_decoded_output[current_thread_id][2],dci_decoded_output[current_thread_id][3], + dci_decoded_output[current_thread_id][4],dci_decoded_output[current_thread_id][5],dci_decoded_output[current_thread_id][6],dci_decoded_output[current_thread_id][7]); +#endif + } + + if (crc==si_rnti) { + dci_alloc[*dci_cnt].format = format_si; + *dci_cnt = *dci_cnt+1; + } else if (crc==p_rnti) { + dci_alloc[*dci_cnt].format = format_p; + *dci_cnt = *dci_cnt+1; + } else if (crc==ra_rnti) { + dci_alloc[*dci_cnt].format = format_ra; + // store first nCCE of group for PUCCH transmission of ACK/NAK + pdcch_vars[eNB_id]->nCCE[nr_tti_rx]=CCEind; + *dci_cnt = *dci_cnt+1; + } else if (crc==pdcch_vars[eNB_id]->crnti) { + + if ((mode&UL_DCI)&&(format_c == format0)&&((dci_decoded_output[current_thread_id][0]&0x80)==0)) {// check if pdu is format 0 or 1A + if (*format0_found == 0) { + dci_alloc[*dci_cnt].format = format0; + *format0_found = 1; + *dci_cnt = *dci_cnt+1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx]=CCEind; + } + } else if (format_c == format0) { // this is a format 1A DCI + dci_alloc[*dci_cnt].format = format1A; + *dci_cnt = *dci_cnt+1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx]=CCEind; + } else { + // store first nCCE of group for PUCCH transmission of ACK/NAK + if (*format_c_found == 0) { + dci_alloc[*dci_cnt].format = format_c; + *dci_cnt = *dci_cnt+1; + *format_c_found = 1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx]=CCEind; + } + } + } + + //LOG_I(PHY,"DCI decoding CRNTI [format: %d, nCCE[nr_tti_rx: %d]: %d ], AggregationLevel %d \n",format_c, nr_tti_rx, pdcch_vars[eNB_id]->nCCE[nr_tti_rx],L2); + // memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes); + + + + switch (1<<L) { + case 1: + *CCEmap|=(1<<(CCEind&0x1f)); + break; + + case 2: + *CCEmap|=(1<<(CCEind&0x1f)); + break; + + case 4: + *CCEmap|=(1<<(CCEind&0x1f)); + break; + + case 8: + *CCEmap|=(1<<(CCEind&0x1f)); + break; + } + +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY,"[DCI search] Found DCI %d rnti %x Aggregation %d length %d format %s in CCE %d (CCEmap %x) candidate %d / %d \n", + *dci_cnt,crc,1<<L,sizeof_bits,dci_format_strings[dci_alloc[*dci_cnt-1].format],CCEind,*CCEmap,m,nb_candidates ); + dump_dci(frame_parms,&dci_alloc[*dci_cnt-1]); + +#endif + return; + } // rnti match + } // CCEmap_cand == 0 + +// if ( agregationLevel != 0xFF && +// (format_c == format0 && m==0 && si_rnti != SI_RNTI)) +// { +// //Only valid for OAI : Save some processing time when looking for DCI format0. From the log we see the DCI only on candidate 0. +// return; +// } + + } // candidate loop +} + +uint16_t dci_CRNTI_decoding_procedure(PHY_VARS_NR_UE *ue, + DCI_ALLOC_t *dci_alloc, + uint8_t DCIFormat, + uint8_t agregationLevel, + int16_t eNB_id, + uint8_t nr_tti_rx) +{ + + uint8_t dci_cnt=0,old_dci_cnt=0; + uint32_t CCEmap0=0,CCEmap1=0,CCEmap2=0; + NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + uint8_t mi = get_mi(&ue->frame_parms,nr_tti_rx); + uint16_t ra_rnti=99; + uint8_t format0_found=0,format_c_found=0; + uint8_t tmode = ue->transmission_mode[eNB_id]; + uint8_t frame_type = frame_parms->frame_type; + uint8_t format0_size_bits=0,format0_size_bytes=0; + uint8_t format1_size_bits=0,format1_size_bytes=0; + dci_detect_mode_t mode = dci_detect_mode_select(&ue->frame_parms,nr_tti_rx); + + switch (frame_parms->N_RB_DL) { + case 6: + if (frame_type == TDD) { + format0_size_bits = sizeof_DCI0_1_5MHz_TDD_1_6_t; + format0_size_bytes = sizeof(DCI0_1_5MHz_TDD_1_6_t); + format1_size_bits = sizeof_DCI1_1_5MHz_TDD_t; + format1_size_bytes = sizeof(DCI1_1_5MHz_TDD_t); + + } else { + format0_size_bits = sizeof_DCI0_1_5MHz_FDD_t; + format0_size_bytes = sizeof(DCI0_1_5MHz_FDD_t); + format1_size_bits = sizeof_DCI1_1_5MHz_FDD_t; + format1_size_bytes = sizeof(DCI1_1_5MHz_FDD_t); + } + + break; + + case 25: + default: + if (frame_type == TDD) { + format0_size_bits = sizeof_DCI0_5MHz_TDD_1_6_t; + format0_size_bytes = sizeof(DCI0_5MHz_TDD_1_6_t); + format1_size_bits = sizeof_DCI1_5MHz_TDD_t; + format1_size_bytes = sizeof(DCI1_5MHz_TDD_t); + } else { + format0_size_bits = sizeof_DCI0_5MHz_FDD_t; + format0_size_bytes = sizeof(DCI0_5MHz_FDD_t); + format1_size_bits = sizeof_DCI1_5MHz_FDD_t; + format1_size_bytes = sizeof(DCI1_5MHz_FDD_t); + } + + break; + + case 50: + if (frame_type == TDD) { + format0_size_bits = sizeof_DCI0_10MHz_TDD_1_6_t; + format0_size_bytes = sizeof(DCI0_10MHz_TDD_1_6_t); + format1_size_bits = sizeof_DCI1_10MHz_TDD_t; + format1_size_bytes = sizeof(DCI1_10MHz_TDD_t); + + } else { + format0_size_bits = sizeof_DCI0_10MHz_FDD_t; + format0_size_bytes = sizeof(DCI0_10MHz_FDD_t); + format1_size_bits = sizeof_DCI1_10MHz_FDD_t; + format1_size_bytes = sizeof(DCI1_10MHz_FDD_t); + } + + break; + + case 100: + if (frame_type == TDD) { + format0_size_bits = sizeof_DCI0_20MHz_TDD_1_6_t; + format0_size_bytes = sizeof(DCI0_20MHz_TDD_1_6_t); + format1_size_bits = sizeof_DCI1_20MHz_TDD_t; + format1_size_bytes = sizeof(DCI1_20MHz_TDD_t); + } else { + format0_size_bits = sizeof_DCI0_20MHz_FDD_t; + format0_size_bytes = sizeof(DCI0_20MHz_FDD_t); + format1_size_bits = sizeof_DCI1_20MHz_FDD_t; + format1_size_bytes = sizeof(DCI1_20MHz_FDD_t); + } + + break; + } + + if (ue->prach_resources[eNB_id]) + ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; + + // Now check UE_SPEC format0/1A ue_spec search spaces at aggregation 8 + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + agregationLevel, + format1A, + format1A, + format1A, + format0, + format0_size_bits, + format0_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (DCIFormat == 1) + { + if ((tmode < 3) || (tmode == 7)) { + //printf("Crnti decoding frame param agregation %d DCI %d \n",agregationLevel,DCIFormat); + + // Now check UE_SPEC format 1 search spaces at aggregation 1 + + //printf("[DCI search] Format 1/1A aggregation 1\n"); + + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 0, + format1A, + format1A, + format1A, + format1, + format1_size_bits, + format1_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff) || + (format_c_found==1)) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + //printf("Crnti 1 decoding frame param agregation %d DCI %d \n",agregationLevel,DCIFormat); + + } + else + { + AssertFatal(0,"Other Transmission mode not yet coded\n"); + } + } + else + { + AssertFatal(0,"DCI format %d not yet implemented \n",DCIFormat); + } + + return(dci_cnt); + +} +*/ + +#ifdef NR_PDCCH_DCI_RUN +uint16_t nr_dci_format_size (NR_DCI_format_t format, + uint8_t pusch_alloc_list, + uint16_t n_RB_ULBWP, + uint16_t n_RB_DLBWP, + uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS]){ +#ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size)-> \n"); +#endif + +/* + * Formats 0_1, not completely implemented. See (*) + */ +// format {0_0,0_1,1_0,1_1,2_0,2_1,2_2,2_3} according to 38.212 Section 7.3.1 +/*#define NBR_NR_FORMATS 8 +#define NBR_NR_DCI FIELDS 48 +#define CARRIER_IND 0 +#define SUL_IND_0_1 1 +#define IDENTIFIER_DCI_FORMATS 2 +#define SLOT_FORMAT_IND 3 +#define PRE_EMPTION_IND 4 +#define TPC_CMD_NUMBER 5 +#define BLOCK_NUMBER 6 +#define BANDWIDTH_PART_IND 7 +#define FREQ_DOM_RESOURCE_ASSIGNMENT_UL 8 +#define FREQ_DOM_RESOURCE_ASSIGNMENT_DL 9 +#define TIME_DOM_RESOURCE_ASSIGNMENT 10 +#define VRB_TO_PRB_MAPPING 11 +#define PRB_BUNDLING_SIZE_IND 12 +#define RATE_MATCHING_IND 13 +#define ZP_CSI_RS_TRIGGER 14 +#define FREQ_HOPPING_FLAG 15 +#define TB1_MCS 16 +#define TB1_NDI 17 +#define TB1_RV 18 +#define TB2_MCS 19 +#define TB2_NDI 20 +#define TB2_RV 21 +#define MCS 22 +#define NDI 23 +#define RV 24 +#define HARQ_PROCESS_NUMBER 25 +#define DAI 26 +#define FIRST_DAI 27 +#define SECOND_DAI 28 +#define TPC_PUSCH 29 +#define TPC_PUCCH 30 +#define PUCCH_RESOURCE_IND 31 +#define PDSCH_TO_HARQ_FEEDBACK_TIME_IND 32 +#define SHORT_MESSAGE_IND 33 +#define SRS_RESOURCE_IND 34 +#define PRECOD_NBR_LAYERS 35 +#define ANTENNA_PORTS 36 +#define TCI 37 +#define SRS_REQUEST 38 +#define TPC_CMD_NUMBER_FORMAT2_3 39 +#define CSI_REQUEST 40 +#define CBGTI 41 +#define CBGFI 42 +#define PTRS_DMRS 43 +#define BETA_OFFSET_IND 44 +#define DMRS_SEQ_INI 45 +#define SUL_IND_0_0 46 +#define PADDING 47*/ + //uint8_t pusch_alloc_list=1; + uint8_t n_zp = 1; // number of ZP CSI-RS resource sets in the higher layer parameter [ZP-CSI-RS-ResourceConfigList]. + uint8_t n_SRS=1; + uint8_t dci_field_size_table [NBR_NR_DCI_FIELDS][NBR_NR_FORMATS] = { // This table contains the number of bits for each field (row) contained in each dci format (column). + // The values of the variables indicate field sizes in number of bits +//Format0_0 Format0_1 Format1_0 Format1_1 Formats2_0/1/2/3 +{0, 3, 0, 3, 0,0,0,0}, // 0 CARRIER_IND: 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] +{0, 0, 0, 0, 0,0,0,0}, // 1 SUL_IND_0_1: +{1, 1, 1, 1, 1,1,1,1}, // 2 IDENTIFIER_DCI_FORMATS: +{0, 0, 0, 0, 1,0,0,0}, // 3 SLOT_FORMAT_IND: size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213] +{0, 0, 0, 0, 0,1,0,0}, // 4 PRE_EMPTION_IND: size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits +{0, 0, 0, 0, 0,0,1,0}, // 5 TPC_CMD_NUMBER: The parameter xxx provided by higher layers determines the index to the TPC command number for an UL of a cell. Each TPC command number is 2 bits +{0, 0, 0, 0, 0,0,0,1}, // 6 BLOCK_NUMBER: starting position of a block is determined by the parameter startingBitOfFormat2_3 +{0, ceil(log2(n_RB_ULBWP)), 0, ceil(log2(n_RB_ULBWP)), 0,0,0,0}, // 7 BANDWIDTH_PART_IND: +{ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)),ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)),0, 0, 0,0,0,0}, // 8 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered + // (NOTE 1) If DCI format 0_0 is monitored in common search space + // and if the number of information bits in the DCI format 0_0 prior to padding + // is larger than the payload size of the DCI format 1_0 monitored in common search space + // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 + // is reduced such that the size of DCI format 0_0 equals to the size of the DCI format 1_0 +{0, 0, ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2)),ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2)),0,0,0,0}, // 9 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: +{log2(pusch_alloc_list), log2(pusch_alloc_list), log2(pusch_alloc_list), log2(pusch_alloc_list), 0,0,0,0}, // 10 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, + // where I the number of entries in the higher layer parameter pusch-AllocationList +{0, 1, 1, 1, 0,0,0,0}, // 11 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0 +{0, 0, 0, 1, 0,0,0,0}, // 12 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] +{0, 0, 0, 2, 0,0,0,0}, // 13 RATE_MATCHING_IND: 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set +{0, 0, 0, log2(n_zp)+1, 0,0,0,0}, // 14 ZP_CSI_RS_TRIGGER: +{1, 1, 0, 0, 0,0,0,0}, // 15 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0 +{0, 0, 0, 5, 0,0,0,0}, // 16 TB1_MCS: +{0, 0, 0, 1, 0,0,0,0}, // 17 TB1_NDI: +{0, 0, 0, 2, 0,0,0,0}, // 18 TB1_RV: +{0, 0, 0, 5, 0,0,0,0}, // 19 TB2_MCS: +{0, 0, 0, 1, 0,0,0,0}, // 20 TB2_NDI: +{0, 0, 0, 2, 0,0,0,0}, // 21 TB2_RV: +{5, 5, 5, 0, 0,0,0,0}, // 22 MCS: +{1, 1, 1, 0, 0,0,0,0}, // 23 NDI: +{2, 2, 2, 0, 0,0,0,0}, // 24 RV: +{4, 4, 4, 4, 0,0,0,0}, // 25 HARQ_PROCESS_NUMBER: +{0, 0, 2, 4, 0,0,0,0}, // 26 DAI: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI + // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI + // 0 otherwise +{0, 2, 0, 0, 0,0,0,0}, // 27 FIRST_DAI: (1 or 2 bits) 1 bit for semi-static HARQ-ACK // 2 bits for dynamic HARQ-ACK codebook with single HARQ-ACK codebook +{0, 2, 0, 0, 0,0,0,0}, // 28 SECOND_DAI: (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks // 0 bits otherwise +{2, 2, 0, 0, 0,0,0,0}, // 29 TPC_PUSCH: +{0, 0, 2, 2, 0,0,0,0}, // 30 TPC_PUCCH: +{0, 0, 3, 3, 0,0,0,0}, // 31 PUCCH_RESOURCE_IND: +{0, 0, 3, 3, 0,0,0,0}, // 32 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: +{0, 0, 0, 0, 0,0,0,0}, // 33 SHORT_MESSAGE_IND: 1 bit if crc scrambled with P-RNTI + // not implemented at the moment +{0, log2(n_SRS), 0, 0, 0,0,0,0}, // 34 SRS_RESOURCE_IND: +{0, 0, 0, 0, 0,0,0,0}, // 35 PRECOD_NBR_LAYERS: +{0, 0, 0, 0, 0,0,0,0}, // 36 ANTENNA_PORTS: +{0, 0, 0, 3, 0,0,0,0}, // 37 TCI: 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits +{0, 3, 0, 0, 0,0,0,2}, // 38 SRS_REQUEST: +{0, 0, 0, 0, 0,0,0,2}, // 39 TPC_CMD_NUMBER_FORMAT2_3: +{0, 6, 0, 0, 0,0,0,0}, // 40 CSI_REQUEST: +{0, 8, 0, 8, 0,0,0,0}, // 41 CBGTI: 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH +{0, 0, 0, 1, 0,0,0,0}, // 42 CBGFI: 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator +{0, 2, 0, 0, 0,0,0,0}, // 43 PTRS_DMRS: +{0, 2, 0, 0, 0,0,0,0}, // 44 BETA_OFFSET_IND: +{0, 1, 0, 1, 0,0,0,0}, // 45 DMRS_SEQ_INI: 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding + //is larger than the number of bits for DCI format 0_0 before padding; 0 bit otherwise +{0, 0, 0, 0, 0,0,0,0}, // 46 SUL_IND_0_0: +{0, 0, 0, 0, 0,0,0,0} // 47 PADDING: (Note 2) If DCI format 0_0 is monitored in common search space + // and if the number of information bits in the DCI format 0_0 prior to padding + // is less than the payload size of the DCI format 1_0 monitored in common search space + // zeros shall be appended to the DCI format 0_0 + // until the payload size equals that of the DCI format 1_0 +}; + +// NOTE 1: adjustments in freq_dom_resource_assignment_UL to be done if necessary +// NOTE 2: adjustments in padding to be done if necessary + +uint8_t dci_size [8] = {0,0,0,0,0,0,0,0}; // will contain size for each format + + for (int i=0 ; i<NBR_NR_FORMATS ; i++) { + for (int j=0; j<NBR_NR_DCI_FIELDS; j++) { + #ifdef NR_PDCCH_DCI_DEBUG + //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size)-> i=%d, j=%d\n", i, j); + #endif + dci_size [i] = dci_size [i] + dci_field_size_table[j][i]; // dci_size[i] contains the size in bits of the dci pdu format i + if (i==(int)format) { // (int)format indicates the position of each format in the table (e.g. format1_0=2 -> position in table is 2) + dci_fields_sizes[j] = dci_field_size_table[j][i]; // dci_fields_sizes[j] contains the sizes of each field (j) for a determined format i + } + } + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_size[%d]=%d for n_RB_ULBWP=%d\n", + i,dci_size[i],n_RB_ULBWP); + #endif + } + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_field_size_table[%d] = { ",format); + for (int j=0; j<NBR_NR_DCI_FIELDS; j++) printf("%d, ",dci_field_size_table[j][(int)format-15]); + printf(" }\n"); + #endif + + if ((format == format0_0) || (format == format1_0)) { + // According to Section 7.3.1.1.1 in TS 38.212 + // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding + // is less than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, + // zeros shall be appended to the DCI format 0_0 until the payload size equals that of the DCI format 1_0. + if (dci_size[0] < dci_size[2]) { // '0' corresponding to index for format0_0 and '2' corresponding to index of format1_0 + if (format == format0_0) { + dci_fields_sizes[PADDING] = dci_size[2] - dci_size[0]; + dci_size[0] = dci_size[2]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); + #endif + } + } + // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding + // is larger than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, + // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 is reduced + // such that the size of DCI format 0_0 equals to the size of the DCI format 1_0.. + if (dci_size[0] > dci_size[2]) { + if (format == format0_0) { + dci_fields_sizes[BANDWIDTH_PART_IND] -= (dci_size[0] - dci_size[2]); + dci_size[0] = dci_size[2]; + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); + #endif + } + } + } + + return dci_size[(int)format]; +} +#endif + +#ifdef NR_PDCCH_DCI_RUN +uint8_t nr_dci_decoding_procedure(int s, + int p, + PHY_VARS_NR_UE *ue, + NR_DCI_ALLOC_t *dci_alloc, + int do_common, + int16_t eNB_id, + uint8_t nr_tti_rx, + uint8_t dci_fields_sizes[48], + uint16_t n_RB_ULBWP, + uint16_t n_RB_DLBWP) { + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure) nr_tti_rx=%d\n",nr_tti_rx); + #endif + uint8_t dci_cnt = 0, old_dci_cnt = 0; + uint32_t CCEmap0 = 0, CCEmap1 = 0, CCEmap2 = 0; + + NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + uint8_t mi;// = get_mi(&ue->frame_parms, nr_tti_rx); + uint16_t ra_rnti = 99; + uint16_t tc_rnti = 1; // FIXME + uint16_t int_rnti = 1; // FIXME + uint16_t sfi_rnti = 1; // FIXME + uint16_t tpc_pusch_rnti =1; // FIXME + uint16_t tpc_pucch_rnti = 1; // FIXME + uint16_t tpc_srs_rnti = 1; // FIXME + uint8_t format0_found = 0, format_c_found = 0; + uint8_t tmode = ue->transmission_mode[eNB_id]; + uint8_t frame_type = frame_parms->frame_type; + //uint8_t dci_fields_sizes[48]; + uint8_t format0_0_size_bits = 0, format0_0_size_bytes = 0; //FIXME + uint8_t format0_1_size_bits = 0, format0_1_size_bytes = 0; //FIXME + uint8_t format1_0_size_bits = 0, format1_0_size_bytes = 0; //FIXME + uint8_t format1_1_size_bits = 0, format1_1_size_bytes = 0; //FIXME + uint8_t format2_0_size_bits = 0, format2_0_size_bytes = 0; //FIXME + uint8_t format2_1_size_bits = 0, format2_1_size_bytes = 0; //FIXME + uint8_t format2_2_size_bits = 0, format2_2_size_bytes = 0; //FIXME + uint8_t format2_3_size_bits = 0, format2_3_size_bytes = 0; //FIXME + + /* + * the following variables have to be removed + */ + uint8_t format1A_size_bits = 0, format1A_size_bytes = 0; + uint8_t format1C_size_bits = 0, format1C_size_bytes = 0; + uint8_t format0_size_bits = 0, format0_size_bytes = 0; + uint8_t format1_size_bits = 0, format1_size_bytes = 0; + uint8_t format2_size_bits = 0, format2_size_bytes = 0; + uint8_t format2A_size_bits = 0, format2A_size_bytes = 0; + /* + * + */ + + /* + * + * The implementation of this function will depend on the information given by the searchSpace IE + * + * In LTE the UE has no knowledge about: + * - the type of search (common or ue-specific) + * - the DCI format it is going to be decoded when performing the PDCCH monitoring + * So the blind decoding has to be done for common and ue-specific searchSpaces for each aggregation level and for each dci format + * + * In NR the UE has a knowledge about the search Space type and the DCI format it is going to be decoded, + * so in the blind decoding we can call the function nr_dci_decoding_procedure0 with the searchSpace type and the dci format parameter + * We will call this function as many times as aggregation levels indicated in searchSpace + * Implementation according to 38.213 v15.1.0 Section 10. + * + */ + + NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; + NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t css_dci_format = pdcch_vars2->searchSpace[s].searchSpaceType.common_dci_formats; + NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t uss_dci_format = pdcch_vars2->searchSpace[s].searchSpaceType.ue_specific_dci_formats; + + // The following initialization is only for test purposes. To be removed + // NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t + css_dci_format = cformat0_0_and_1_0; + //NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t + uss_dci_format = uformat0_0_and_1_0; + + /* + * Possible overlap between RE for SS/PBCH blocks (described in section 10, 38.213) has not been implemented yet + * This can be implemented by setting variable 'mode = NO_DCI' when overlap occurs + */ + //dci_detect_mode_t mode = 3; //dci_detect_mode_select(&ue->frame_parms, nr_tti_rx); + + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> searSpaceType=%d\n",do_common); + if (do_common) { + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> css_dci_format=%d\n",css_dci_format); + } else { + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> uss_dci_format=%d\n",uss_dci_format); + } + #endif + // A set of PDCCH candidates for a UE to monitor is defined in terms of PDCCH search spaces + if (do_common) { // COMMON SearchSpaceType assigned to current SearchSpace/CORESET + // Type0-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI + // number of consecutive resource blocks and a number of consecutive symbols for + // the control resource set of the Type0-PDCCH common search space from + // the four most significant bits of RMSI-PDCCH-Config as described in Tables 13-1 through 13-10 + // and determines PDCCH monitoring occasions + // from the four least significant bits of RMSI-PDCCH-Config, + // included in MasterInformationBlock, as described in Tables 13-11 through 13-15 + // Type0A-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI + // Type1-PDCCH common search space for a DCI format with CRC scrambled by a RA-RNTI, or a TC-RNTI, or a C-RNTI + // Type2-PDCCH common search space for a DCI format with CRC scrambled by a P-RNTI + if (css_dci_format == cformat0_0_and_1_0) { + // 38.213 v15.1.0 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE + // aggregation level for Type0/Type0A/Type2-PDCCH common search space + // CCE Aggregation Level Number of Candidates + // 4 4 + // 8 2 + // 16 1 + // FIXME + // We shall consider Table 10.1-1 to calculate the blind decoding only for Type0/Type0A/Type2-PDCCH + // Shall we consider the nrofCandidates in SearSpace IE that considers Aggregation Levels 1,2,4,8,16? Our implementation considers Table 10.1-1 + + // blind decoding (Type0-PDCCH,Type0A-PDCCH,Type1-PDCCH,Type2-PDCCH) + // for format0_0 => we are NOT implementing format0_0 for common search spaces. FIXME! + + // for format1_0, first we calculate dci pdu size + format1_0_size_bits = nr_dci_format_size(format1_0,1,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + // the second parameter '1' is the pusch_alloc_list used to calculate size of field TIME_DOM_RESOURCE_ASSIGNMENT + //format1_0_size_bits = nr_dci_format_size(2,1,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format1_0_size_bytes = (format1_0_size_bits%8 == 0) ? (uint8_t)floor(format1_0_size_bits/8) : (uint8_t)(floor(format1_0_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format1_0_size_bits=%d, format1_0_size_bytes=%d\n", + css_dci_format,format1_0_size_bits,format1_0_size_bytes); + #endif + // for aggregation level 4. The number of candidates (L2=4) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<<2)); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 2, + cformat0_0_and_1_0, format1A, format1A, format0, + format1_0_size_bits, format1A_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // for aggregation level 8. The number of candidates (L2=8) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<<3)); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 3, + cformat0_0_and_1_0, format1A, format1A, format0, + format1_0_size_bits, format1A_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // for aggregation level 16. The number of candidates (L2=16) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<<4)); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 4, + cformat0_0_and_1_0, format1A, format1A, format0, + format1_0_size_bits, format1A_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + } + + // Type3-PDCCH common search space for a DCI format with CRC scrambled by INT-RNTI, or SFI-RNTI, + // or TPC-PUSCH-RNTI, or TPC-PUCCH-RNTI, or TPC-SRS-RNTI, or C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI + if (css_dci_format == cformat2_0) { + // for format2_0, first we calculate dci pdu size + format2_0_size_bits = nr_dci_format_size(format2_0,0,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format2_0_size_bytes = (format2_0_size_bits%8 == 0) ? (uint8_t)floor(format2_0_size_bits/8) : (uint8_t)(floor(format2_0_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_0_size_bits=%d, format2_0_size_bytes=%d\n", + css_dci_format,format2_0_size_bits,format2_0_size_bytes); + #endif + // for aggregation level 1. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 + nr_dci_decoding_procedure0(s,p,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 0, + format1A, format1A, format1A, format0, + format1A_size_bits, format1A_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // for aggregation level 2. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 + nr_dci_decoding_procedure0(s,p,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 1, + format1A, format1A, format1A, format0, + format1A_size_bits, format1A_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // for aggregation level 4. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 + nr_dci_decoding_procedure0(s,p,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 2, + format1A, format1A, format1A, format0, + format1A_size_bits, format1A_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // for aggregation level 8. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 + nr_dci_decoding_procedure0(s,p,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 3, + format1A, format1A, format1A, format0, + format1A_size_bits, format1A_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // for aggregation level 16. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 + nr_dci_decoding_procedure0(s,p,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 4, + format1A, format1A, format1A, format0, + format1A_size_bits, format1A_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + } + if (css_dci_format == cformat2_1) { + // for format2_1, first we calculate dci pdu size + format2_1_size_bits = nr_dci_format_size(format2_1,0,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format2_1_size_bytes = (format2_1_size_bits%8 == 0) ? (uint8_t)floor(format2_1_size_bits/8) : (uint8_t)(floor(format2_1_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_1_size_bits=%d, format2_1_size_bytes=%d\n", + css_dci_format,format2_1_size_bits,format2_1_size_bytes); + #endif + } + if (css_dci_format == cformat2_2) { + // for format2_2, first we calculate dci pdu size + format2_2_size_bits = nr_dci_format_size(format2_2,0,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format2_2_size_bytes = (format2_2_size_bits%8 == 0) ? (uint8_t)floor(format2_2_size_bits/8) : (uint8_t)(floor(format2_2_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_2_size_bits=%d, format2_2_size_bytes=%d\n", + css_dci_format,format2_2_size_bits,format2_2_size_bytes); + #endif + } + if (css_dci_format == cformat2_3) { + // for format2_1, first we calculate dci pdu size + format2_3_size_bits = nr_dci_format_size(format2_3,0,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format2_3_size_bytes = (format2_3_size_bits%8 == 0) ? (uint8_t)floor(format2_3_size_bits/8) : (uint8_t)(floor(format2_3_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_3_size_bits=%d, format2_3_size_bytes=%d\n", + css_dci_format,format2_3_size_bits,format2_3_size_bytes); + #endif + } + } else { // UE-SPECIFIC SearchSpaceType assigned to current SearchSpace/CORESET + // UE-specific search space for a DCI format with CRC scrambled by C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI + if (uss_dci_format == uformat0_0_and_1_0) { + // for format0_0, first we calculate dci pdu size + format0_0_size_bits = nr_dci_format_size(format0_0,1,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format0_0_size_bytes = (format0_0_size_bits%8 == 0) ? (uint8_t)floor(format0_0_size_bits/8) : (uint8_t)(floor(format0_0_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format0_0_size_bits=%d, format0_0_size_bytes=%d\n", + css_dci_format,format0_0_size_bits,format0_0_size_bytes); + #endif + // blind decoding format0_0 for aggregation level 1. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 1, format0_0_size_bits=%d, format0_0_size_bytes=%d\n", + uss_dci_format,format0_0_size_bits,format0_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 0, + format1A, format1A, format1A, format0, + format0_0_size_bits, format0_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // blind decoding format0_0 for aggregation level 2. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 2, format0_0_size_bits=%d, format0_0_size_bytes=%d\n", + uss_dci_format,format0_0_size_bits,format0_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 1, + format1A, format1A, format1A, format0, + format0_0_size_bits, format0_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // blind decoding format0_0 for aggregation level 4. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 4, format0_0_size_bits=%d, format0_0_size_bytes=%d\n", + uss_dci_format,format0_0_size_bits,format0_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 2, + format1A, format1A, format1A, format0, + format0_0_size_bits, format0_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // blind decoding format0_0 for aggregation level 8. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 8, format0_0_size_bits=%d, format0_0_size_bytes=%d\n", + uss_dci_format,format0_0_size_bits,format0_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 3, + format1A, format1A, format1A, format0, + format0_0_size_bits, format0_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // blind decoding format0_0 for aggregation level 16. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 16, format0_0_size_bits=%d, format0_0_size_bytes=%d\n", + uss_dci_format,format0_0_size_bits,format0_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 4, + format1A, format1A, format1A, format0, + format0_0_size_bits, format0_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + + // for format1_0, first we calculate dci pdu size + format1_0_size_bits = nr_dci_format_size(format1_0,1,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format1_0_size_bytes = (format1_0_size_bits%8 == 0) ? (uint8_t)floor(format1_0_size_bits/8) : (uint8_t)(floor(format1_0_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format1_0_size_bits=%d, format1_0_size_bytes=%d\n", + css_dci_format,format1_0_size_bits,format1_0_size_bytes); + #endif + // blind decoding format1_0 for aggregation level 1. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 1, format1_0_size_bits=%d, format1_0_size_bytes=%d\n", + uss_dci_format,format1_0_size_bits,format1_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 0, + format1A, format1A, format1A, format0, + format1_0_size_bits, format1_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // blind decoding format1_0 for aggregation level 2. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 2, format1_0_size_bits=%d, format1_0_size_bytes=%d\n", + uss_dci_format,format1_0_size_bits,format1_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 1, + format1A, format1A, format1A, format0, + format1_0_size_bits, format1_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // blind decoding format1_0 for aggregation level 4. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 4, format1_0_size_bits=%d, format1_0_size_bytes=%d\n", + uss_dci_format,format1_0_size_bits,format1_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 2, + format1A, format1A, format1A, format0, + format1_0_size_bits, format1_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // blind decoding format1_0 for aggregation level 8. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 8, format1_0_size_bits=%d, format1_0_size_bytes=%d\n", + uss_dci_format,format1_0_size_bits,format1_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 3, + format1A, format1A, format1A, format0, + format1_0_size_bits, format1_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + // blind decoding format1_0 for aggregation level 16. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> ue-Specific searchSpaces with format uss_dci_format=%d and aggregation level 16, format1_0_size_bits=%d, format1_0_size_bytes=%d\n", + uss_dci_format,format1_0_size_bits,format1_0_size_bytes); + #endif + nr_dci_decoding_procedure0(s,p,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, tc_rnti, int_rnti, sfi_rnti, tpc_pusch_rnti, tpc_pucch_rnti, tpc_srs_rnti, 4, + format1A, format1A, format1A, format0, + format1_0_size_bits, format1_0_size_bytes, &dci_cnt, + &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); + } + if (uss_dci_format == uformat0_1_and_1_1) { // Not implemented yet. FIXME!!! + // for format0_1, first we calculate dci pdu size + format0_1_size_bits = nr_dci_format_size(format0_1,1,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format0_1_size_bytes = (format0_1_size_bits%8 == 0) ? (uint8_t)floor(format0_1_size_bits/8) : (uint8_t)(floor(format0_1_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format0_1_size_bits=%d, format0_1_size_bytes=%d\n", + css_dci_format,format0_1_size_bits,format0_1_size_bytes); + #endif + // blind decoding format0_1 for aggregation level 1. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + // blind decoding format0_1 for aggregation level 2. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + // blind decoding format0_1 for aggregation level 4. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + // blind decoding format0_1 for aggregation level 8. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + // blind decoding format0_1 for aggregation level 16. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + + // for format1_1, first we calculate dci pdu size + format1_1_size_bits = nr_dci_format_size(format1_1,1,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); + format1_1_size_bytes = (format1_1_size_bits%8 == 0) ? (uint8_t)floor(format1_1_size_bits/8) : (uint8_t)(floor(format1_1_size_bits/8) + 1); + #ifdef NR_PDCCH_DCI_DEBUG + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format1_1_size_bits=%d, format1_1_size_bytes=%d\n", + css_dci_format,format1_1_size_bits,format1_1_size_bytes); + #endif + // blind decoding format1_1 for aggregation level 1. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + // blind decoding format1_1 for aggregation level 2. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + // blind decoding format1_1 for aggregation level 4. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + // blind decoding format1_1 for aggregation level 8. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + // blind decoding format1_1 for aggregation level 16. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 + } + } + return(dci_cnt); +} +#endif + + + + + +/* +uint16_t dci_decoding_procedure(PHY_VARS_NR_UE *ue, + DCI_ALLOC_t *dci_alloc, + int do_common, + int16_t eNB_id, + uint8_t nr_tti_rx) +{ + + uint8_t dci_cnt=0,old_dci_cnt=0; + uint32_t CCEmap0=0,CCEmap1=0,CCEmap2=0; + NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + uint8_t mi = get_mi(&ue->frame_parms,nr_tti_rx); + uint16_t ra_rnti=99; + uint8_t format0_found=0,format_c_found=0; + uint8_t tmode = ue->transmission_mode[eNB_id]; + uint8_t frame_type = frame_parms->frame_type; + uint8_t format1A_size_bits=0,format1A_size_bytes=0; + uint8_t format1C_size_bits=0,format1C_size_bytes=0; + uint8_t format0_size_bits=0,format0_size_bytes=0; + uint8_t format1_size_bits=0,format1_size_bytes=0; + uint8_t format2_size_bits=0,format2_size_bytes=0; + uint8_t format2A_size_bits=0,format2A_size_bytes=0; + dci_detect_mode_t mode = dci_detect_mode_select(&ue->frame_parms,nr_tti_rx); + + switch (frame_parms->N_RB_DL) { + case 6: + if (frame_type == TDD) { + format1A_size_bits = sizeof_DCI1A_1_5MHz_TDD_1_6_t; + format1A_size_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); + format1C_size_bits = sizeof_DCI1C_1_5MHz_t; + format1C_size_bytes = sizeof(DCI1C_1_5MHz_t); + format0_size_bits = sizeof_DCI0_1_5MHz_TDD_1_6_t; + format0_size_bytes = sizeof(DCI0_1_5MHz_TDD_1_6_t); + format1_size_bits = sizeof_DCI1_1_5MHz_TDD_t; + format1_size_bytes = sizeof(DCI1_1_5MHz_TDD_t); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + format2_size_bits = sizeof_DCI2_1_5MHz_2A_TDD_t; + format2_size_bytes = sizeof(DCI2_1_5MHz_2A_TDD_t); + format2A_size_bits = sizeof_DCI2A_1_5MHz_2A_TDD_t; + format2A_size_bytes = sizeof(DCI2A_1_5MHz_2A_TDD_t); + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + format2_size_bits = sizeof_DCI2_1_5MHz_4A_TDD_t; + format2_size_bytes = sizeof(DCI2_1_5MHz_4A_TDD_t); + format2A_size_bits = sizeof_DCI2A_1_5MHz_4A_TDD_t; + format2A_size_bytes = sizeof(DCI2A_1_5MHz_4A_TDD_t); + } + } else { + format1A_size_bits = sizeof_DCI1A_1_5MHz_FDD_t; + format1A_size_bytes = sizeof(DCI1A_1_5MHz_FDD_t); + format1C_size_bits = sizeof_DCI1C_1_5MHz_t; + format1C_size_bytes = sizeof(DCI1C_1_5MHz_t); + format0_size_bits = sizeof_DCI0_1_5MHz_FDD_t; + format0_size_bytes = sizeof(DCI0_1_5MHz_FDD_t); + format1_size_bits = sizeof_DCI1_1_5MHz_FDD_t; + format1_size_bytes = sizeof(DCI1_1_5MHz_FDD_t); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + format2_size_bits = sizeof_DCI2_1_5MHz_2A_FDD_t; + format2_size_bytes = sizeof(DCI2_1_5MHz_2A_FDD_t); + format2A_size_bits = sizeof_DCI2A_1_5MHz_2A_FDD_t; + format2A_size_bytes = sizeof(DCI2A_1_5MHz_2A_FDD_t); + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + format2_size_bits = sizeof_DCI2_1_5MHz_4A_FDD_t; + format2_size_bytes = sizeof(DCI2_1_5MHz_4A_FDD_t); + format2A_size_bits = sizeof_DCI2A_1_5MHz_4A_FDD_t; + format2A_size_bytes = sizeof(DCI2A_1_5MHz_4A_FDD_t); + } + } + + break; + + case 25: + default: + if (frame_type == TDD) { + format1A_size_bits = sizeof_DCI1A_5MHz_TDD_1_6_t; + format1A_size_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); + format1C_size_bits = sizeof_DCI1C_5MHz_t; + format1C_size_bytes = sizeof(DCI1C_5MHz_t); + format0_size_bits = sizeof_DCI0_5MHz_TDD_1_6_t; + format0_size_bytes = sizeof(DCI0_5MHz_TDD_1_6_t); + format1_size_bits = sizeof_DCI1_5MHz_TDD_t; + format1_size_bytes = sizeof(DCI1_5MHz_TDD_t); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + format2_size_bits = sizeof_DCI2_5MHz_2A_TDD_t; + format2_size_bytes = sizeof(DCI2_5MHz_2A_TDD_t); + format2A_size_bits = sizeof_DCI2A_5MHz_2A_TDD_t; + format2A_size_bytes = sizeof(DCI2A_5MHz_2A_TDD_t); + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + format2_size_bits = sizeof_DCI2_5MHz_4A_TDD_t; + format2_size_bytes = sizeof(DCI2_5MHz_4A_TDD_t); + format2A_size_bits = sizeof_DCI2A_5MHz_4A_TDD_t; + format2A_size_bytes = sizeof(DCI2A_5MHz_4A_TDD_t); + } + } else { + format1A_size_bits = sizeof_DCI1A_5MHz_FDD_t; + format1A_size_bytes = sizeof(DCI1A_5MHz_FDD_t); + format1C_size_bits = sizeof_DCI1C_5MHz_t; + format1C_size_bytes = sizeof(DCI1C_5MHz_t); + format0_size_bits = sizeof_DCI0_5MHz_FDD_t; + format0_size_bytes = sizeof(DCI0_5MHz_FDD_t); + format1_size_bits = sizeof_DCI1_5MHz_FDD_t; + format1_size_bytes = sizeof(DCI1_5MHz_FDD_t); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + format2_size_bits = sizeof_DCI2_5MHz_2A_FDD_t; + format2_size_bytes = sizeof(DCI2_5MHz_2A_FDD_t); + format2A_size_bits = sizeof_DCI2A_5MHz_2A_FDD_t; + format2A_size_bytes = sizeof(DCI2A_5MHz_2A_FDD_t); + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + format2_size_bits = sizeof_DCI2_5MHz_4A_FDD_t; + format2_size_bytes = sizeof(DCI2_5MHz_4A_FDD_t); + format2A_size_bits = sizeof_DCI2A_5MHz_4A_FDD_t; + format2A_size_bytes = sizeof(DCI2A_5MHz_4A_FDD_t); + } + } + + break; + + case 50: + if (frame_type == TDD) { + format1A_size_bits = sizeof_DCI1A_10MHz_TDD_1_6_t; + format1A_size_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); + format1C_size_bits = sizeof_DCI1C_10MHz_t; + format1C_size_bytes = sizeof(DCI1C_10MHz_t); + format0_size_bits = sizeof_DCI0_10MHz_TDD_1_6_t; + format0_size_bytes = sizeof(DCI0_10MHz_TDD_1_6_t); + format1_size_bits = sizeof_DCI1_10MHz_TDD_t; + format1_size_bytes = sizeof(DCI1_10MHz_TDD_t); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + format2_size_bits = sizeof_DCI2_10MHz_2A_TDD_t; + format2_size_bytes = sizeof(DCI2_10MHz_2A_TDD_t); + format2A_size_bits = sizeof_DCI2A_10MHz_2A_TDD_t; + format2A_size_bytes = sizeof(DCI2A_10MHz_2A_TDD_t); + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + format2_size_bits = sizeof_DCI2_10MHz_4A_TDD_t; + format2_size_bytes = sizeof(DCI2_10MHz_4A_TDD_t); + format2A_size_bits = sizeof_DCI2A_10MHz_4A_TDD_t; + format2A_size_bytes = sizeof(DCI2A_10MHz_4A_TDD_t); + } + } else { + format1A_size_bits = sizeof_DCI1A_10MHz_FDD_t; + format1A_size_bytes = sizeof(DCI1A_10MHz_FDD_t); + format1C_size_bits = sizeof_DCI1C_10MHz_t; + format1C_size_bytes = sizeof(DCI1C_10MHz_t); + format0_size_bits = sizeof_DCI0_10MHz_FDD_t; + format0_size_bytes = sizeof(DCI0_10MHz_FDD_t); + format1_size_bits = sizeof_DCI1_10MHz_FDD_t; + format1_size_bytes = sizeof(DCI1_10MHz_FDD_t); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + format2_size_bits = sizeof_DCI2_10MHz_2A_FDD_t; + format2_size_bytes = sizeof(DCI2_10MHz_2A_FDD_t); + format2A_size_bits = sizeof_DCI2A_10MHz_2A_FDD_t; + format2A_size_bytes = sizeof(DCI2A_10MHz_2A_FDD_t); + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + format2_size_bits = sizeof_DCI2_10MHz_4A_FDD_t; + format2_size_bytes = sizeof(DCI2_10MHz_4A_FDD_t); + format2A_size_bits = sizeof_DCI2A_10MHz_4A_FDD_t; + format2A_size_bytes = sizeof(DCI2A_10MHz_4A_FDD_t); + } + } + + break; + + case 100: + if (frame_type == TDD) { + format1A_size_bits = sizeof_DCI1A_20MHz_TDD_1_6_t; + format1A_size_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t); + format1C_size_bits = sizeof_DCI1C_20MHz_t; + format1C_size_bytes = sizeof(DCI1C_20MHz_t); + format0_size_bits = sizeof_DCI0_20MHz_TDD_1_6_t; + format0_size_bytes = sizeof(DCI0_20MHz_TDD_1_6_t); + format1_size_bits = sizeof_DCI1_20MHz_TDD_t; + format1_size_bytes = sizeof(DCI1_20MHz_TDD_t); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + format2_size_bits = sizeof_DCI2_20MHz_2A_TDD_t; + format2_size_bytes = sizeof(DCI2_20MHz_2A_TDD_t); + format2A_size_bits = sizeof_DCI2A_20MHz_2A_TDD_t; + format2A_size_bytes = sizeof(DCI2A_20MHz_2A_TDD_t); + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + format2_size_bits = sizeof_DCI2_20MHz_4A_TDD_t; + format2_size_bytes = sizeof(DCI2_20MHz_4A_TDD_t); + format2A_size_bits = sizeof_DCI2A_20MHz_4A_TDD_t; + format2A_size_bytes = sizeof(DCI2A_20MHz_4A_TDD_t); + } + } else { + format1A_size_bits = sizeof_DCI1A_20MHz_FDD_t; + format1A_size_bytes = sizeof(DCI1A_20MHz_FDD_t); + format1C_size_bits = sizeof_DCI1C_20MHz_t; + format1C_size_bytes = sizeof(DCI1C_20MHz_t); + format0_size_bits = sizeof_DCI0_20MHz_FDD_t; + format0_size_bytes = sizeof(DCI0_20MHz_FDD_t); + format1_size_bits = sizeof_DCI1_20MHz_FDD_t; + format1_size_bytes = sizeof(DCI1_20MHz_FDD_t); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + format2_size_bits = sizeof_DCI2_20MHz_2A_FDD_t; + format2_size_bytes = sizeof(DCI2_20MHz_2A_FDD_t); + format2A_size_bits = sizeof_DCI2A_20MHz_2A_FDD_t; + format2A_size_bytes = sizeof(DCI2A_20MHz_2A_FDD_t); + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + format2_size_bits = sizeof_DCI2_20MHz_4A_FDD_t; + format2_size_bytes = sizeof(DCI2_20MHz_4A_FDD_t); + format2A_size_bits = sizeof_DCI2A_20MHz_4A_FDD_t; + format2A_size_bytes = sizeof(DCI2A_20MHz_4A_FDD_t); + } + } + + break; + } + + if (do_common == 1) { +#ifdef DEBUG_DCI_DECODING + printf("[DCI search] doing common search/format0 aggregation 4\n"); +#endif + + if (ue->prach_resources[eNB_id]) + ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; + + // First check common search spaces at aggregation 4 (SI_RNTI, P_RNTI and RA_RNTI format 0/1A), + // and UE_SPEC format0 (PUSCH) too while we're at it + dci_decoding_procedure0(pdcch_vars,1,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0) , + ra_rnti, + P_RNTI, + 2, + format1A, + format1A, + format1A, + format0, + format1A_size_bits, + format1A_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff) || + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + // Now check common search spaces at aggregation 4 (SI_RNTI,P_RNTI and RA_RNTI and C-RNTI format 1C), + // and UE_SPEC format0 (PUSCH) too while we're at it + dci_decoding_procedure0(pdcch_vars,1,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 2, + format1C, + format1C, + format1C, + format1C, + format1C_size_bits, + format1C_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff) || + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + // Now check common search spaces at aggregation 8 (SI_RNTI,P_RNTI and RA_RNTI format 1A), + // and UE_SPEC format0 (PUSCH) too while we're at it + // printf("[DCI search] doing common search/format0 aggregation 3\n"); +#ifdef DEBUG_DCI_DECODING + printf("[DCI search] doing common search/format0 aggregation 8\n"); +#endif + dci_decoding_procedure0(pdcch_vars,1,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + P_RNTI, + ra_rnti, + 3, + format1A, + format1A, + format1A, + format0, + format1A_size_bits, + format1A_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + // Now check common search spaces at aggregation 8 (SI_RNTI and RA_RNTI and C-RNTI format 1C), + // and UE_SPEC format0 (PUSCH) too while we're at it + dci_decoding_procedure0(pdcch_vars,1,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 3, + format1C, + format1C, + format1C, + format1C, + format1C_size_bits, + format1C_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + //#endif + + } + + if (ue->UE_mode[eNB_id] <= PRACH) + return(dci_cnt); + + if (ue->prach_resources[eNB_id]) + ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; + + // Now check UE_SPEC format0/1A ue_spec search spaces at aggregation 8 + // printf("[DCI search] Format 0/1A aggregation 8\n"); + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 0, + format1A, + format1A, + format1A, + format0, + format0_size_bits, + format0_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + //printf("[DCI search] Format 0 aggregation 1 dci_cnt %d\n",dci_cnt); + + if (dci_cnt == 0) + { + // Now check UE_SPEC format 0 search spaces at aggregation 4 + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 1, + format1A, + format1A, + format1A, + format0, + format0_size_bits, + format0_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + + //printf("[DCI search] Format 0 aggregation 2 dci_cnt %d\n",dci_cnt); + } + + if (dci_cnt == 0) + { + // Now check UE_SPEC format 0 search spaces at aggregation 2 + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 2, + format1A, + format1A, + format1A, + format0, + format0_size_bits, + format0_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + //printf("[DCI search] Format 0 aggregation 4 dci_cnt %d\n",dci_cnt); + } + + if (dci_cnt == 0) + { + // Now check UE_SPEC format 0 search spaces at aggregation 1 + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 3, + format1A, + format1A, + format1A, + format0, + format0_size_bits, + format0_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + //printf("[DCI search] Format 0 aggregation 8 dci_cnt %d\n",dci_cnt); + + } + // These are for CRNTI based on transmission mode + if ((tmode < 3) || (tmode == 7)) { + // Now check UE_SPEC format 1 search spaces at aggregation 1 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 0, + format1A, + format1A, + format1A, + format1, + format1_size_bits, + format1_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + //printf("[DCI search] Format 1 aggregation 1 dci_cnt %d\n",dci_cnt); + + if ((CCEmap0==0xffff) || + (format_c_found==1)) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + // Now check UE_SPEC format 1 search spaces at aggregation 2 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 1, + format1A, + format1A, + format1A, + format1, + format1_size_bits, + format1_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + //printf("[DCI search] Format 1 aggregation 2 dci_cnt %d\n",dci_cnt); + + if ((CCEmap0==0xffff)|| + (format_c_found==1)) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + // Now check UE_SPEC format 1 search spaces at aggregation 4 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 2, + format1A, + format1A, + format1A, + format1, + format1_size_bits, + format1_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + //printf("[DCI search] Format 1 aggregation 4 dci_cnt %d\n",dci_cnt); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + //#ifdef ALL_AGGREGATION + // Now check UE_SPEC format 1 search spaces at aggregation 8 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 3, + format1A, + format1A, + format1A, + format1, + format1_size_bits, + format1_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + //printf("[DCI search] Format 1 aggregation 8 dci_cnt %d\n",dci_cnt); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + //#endif //ALL_AGGREGATION + } else if (tmode == 3) { + + + LOG_D(PHY," Now check UE_SPEC format 2A_2A search aggregation 1 dci length: %d[bits] %d[bytes]\n",format2A_size_bits,format2A_size_bytes); + // Now check UE_SPEC format 2A_2A search spaces at aggregation 1 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 0, + format1A, + format1A, + format1A, + format2A, + format2A_size_bits, + format2A_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + LOG_D(PHY," format 2A_2A search CCEmap0 %x, format0_found %d, format_c_found %d \n", CCEmap0, format0_found, format_c_found); + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + LOG_D(PHY," format 2A_2A search dci_cnt %d, old_dci_cn t%d \n", dci_cnt, old_dci_cnt); + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + // Now check UE_SPEC format 2 search spaces at aggregation 2 + LOG_D(PHY," Now check UE_SPEC format 2A_2A search aggregation 2 dci length: %d[bits] %d[bytes]\n",format2A_size_bits,format2A_size_bytes); + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 1, + format1A, + format1A, + format1A, + format2A, + format2A_size_bits, + format2A_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + LOG_D(PHY," format 2A_2A search dci_cnt %d, old_dci_cn t%d \n", dci_cnt, old_dci_cnt); + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + // Now check UE_SPEC format 2_2A search spaces at aggregation 4 + LOG_D(PHY," Now check UE_SPEC format 2_2A search spaces at aggregation 4 \n"); + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 2, + format1A, + format1A, + format1A, + format2A, + format2A_size_bits, + format2A_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + LOG_D(PHY," format 2A_2A search dci_cnt %d, old_dci_cn t%d \n", dci_cnt, old_dci_cnt); + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + //#ifdef ALL_AGGREGATION + // Now check UE_SPEC format 2_2A search spaces at aggregation 8 + LOG_D(PHY," Now check UE_SPEC format 2_2A search spaces at aggregation 8 dci length: %d[bits] %d[bytes]\n",format2A_size_bits,format2A_size_bytes); + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 3, + format1A, + format1A, + format1A, + format2A, + format2A_size_bits, + format2A_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + //#endif + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + LOG_D(PHY," format 2A_2A search dci_cnt %d, old_dci_cn t%d \n", dci_cnt, old_dci_cnt); + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + } else if (tmode == 4) { + + // Now check UE_SPEC format 2_2A search spaces at aggregation 1 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 0, + format1A, + format1A, + format1A, + format2, + format2_size_bits, + format2_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + // Now check UE_SPEC format 2 search spaces at aggregation 2 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 1, + format1A, + format1A, + format1A, + format2, + format2_size_bits, + format2_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + // Now check UE_SPEC format 2_2A search spaces at aggregation 4 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 2, + format1A, + format1A, + format1A, + format2, + format2_size_bits, + format2_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + //#ifdef ALL_AGGREGATION + // Now check UE_SPEC format 2_2A search spaces at aggregation 8 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 3, + format1A, + format1A, + format1A, + format2, + format2_size_bits, + format2_size_bytes, + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + //#endif + } else if ((tmode==5) || (tmode==6)) { // This is MU-MIMO + + // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 1 +#ifdef DEBUG_DCI_DECODING + LOG_I(PHY," MU-MIMO check UE_SPEC format 1E_2A_M10PRB\n"); +#endif + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 0, + format1A, + format1A, + format1A, + format1E_2A_M10PRB, + sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, + sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 2 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 1, + format1A, + format1A, + format1A, + format1E_2A_M10PRB, + sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, + sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 4 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 2, + format1A, + format1A, + format1A, + format1E_2A_M10PRB, + sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, + sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + //#ifdef ALL_AGGREGATION + + // Now check UE_SPEC format 1E_2A_M10PRB search spaces at aggregation 8 + old_dci_cnt=dci_cnt; + dci_decoding_procedure0(pdcch_vars,0,mode, + nr_tti_rx, + dci_alloc, + eNB_id, + ue->current_thread_id[nr_tti_rx], + frame_parms, + mi, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), + ra_rnti, + P_RNTI, + 3, + format1A, + format1A, + format1A, + format1E_2A_M10PRB, + sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, + sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), + &dci_cnt, + &format0_found, + &format_c_found, + &CCEmap0, + &CCEmap1, + &CCEmap2); + + if ((CCEmap0==0xffff)|| + ((format0_found==1)&&(format_c_found==1))) + return(dci_cnt); + + if (dci_cnt>old_dci_cnt) + return(dci_cnt); + + //#endif //ALL_AGGREGATION + + } + + return(dci_cnt); +} +*/ +#ifdef PHY_ABSTRACTION +uint16_t dci_decoding_procedure_emul(NR_UE_PDCCH **pdcch_vars, + uint8_t num_ue_spec_dci, + uint8_t num_common_dci, + DCI_ALLOC_t *dci_alloc_tx, + DCI_ALLOC_t *dci_alloc_rx, + int16_t eNB_id) +{ + + uint8_t dci_cnt=0,i; + + memcpy(dci_alloc_rx,dci_alloc_tx,num_common_dci*sizeof(DCI_ALLOC_t)); + dci_cnt = num_common_dci; + LOG_D(PHY,"[DCI][EMUL] : num_common_dci %d\n",num_common_dci); + + for (i=num_common_dci; i<(num_ue_spec_dci+num_common_dci); i++) { + LOG_D(PHY,"[DCI][EMUL] Checking dci %d => %x format %d (bit 0 %d)\n",i,pdcch_vars[eNB_id]->crnti,dci_alloc_tx[i].format, + dci_alloc_tx[i].dci_pdu[0]&0x80); + + if (dci_alloc_tx[i].rnti == pdcch_vars[eNB_id]->crnti) { + memcpy(dci_alloc_rx+dci_cnt,dci_alloc_tx+i,sizeof(DCI_ALLOC_t)); + dci_cnt++; + } + } + + + return(dci_cnt); +} +#endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.h b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.h new file mode 100644 index 0000000000000000000000000000000000000000..5d12b1e2a01f9cefaa6674615f608322f6afa40d --- /dev/null +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.h @@ -0,0 +1,111 @@ +/* + * 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 + */ + +/*! \file PHY/LTE_TRANSPORT/dci_nr.h +* \brief typedefs for NR DCI structures from 38-212. +* \author R. Knopp, A. Mico Pereperez +* \date 2018 +* \version 0.1 +* \company Eurecom +* \email: knopp@eurecom.fr +* \note +* \warning +*/ +#ifndef USER_MODE +#include "PHY/types.h" +#else +#include <stdint.h> +#endif + + + +#define MAX_DCI_SIZE_BITS 45 + + +#define NR_PDCCH_DCI_H +#ifdef NR_PDCCH_DCI_H +struct NR_DCI_INFO_EXTRACTED { + uint8_t carrier_ind ; // 0 CARRIER_IND: 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] + uint8_t sul_ind_0_1 ; // 1 SUL_IND_0_1: + uint8_t identifier_dci_formats ; // 2 IDENTIFIER_DCI_FORMATS: + uint8_t slot_format_ind ; // 3 SLOT_FORMAT_IND: size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213] + uint8_t pre_emption_ind ; // 4 PRE_EMPTION_IND: size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits + uint8_t tpc_cmd_number ; // 5 TPC_CMD_NUMBER: The parameter xxx provided by higher layers determines the index to the TPC command number for an UL of a cell. Each TPC command number is 2 bits + uint8_t block_number ; // 6 BLOCK_NUMBER: starting position of a block is determined by the parameter startingBitOfFormat2_3 + uint8_t bandwidth_part_ind ; // 7 BANDWIDTH_PART_IND: + uint16_t freq_dom_resource_assignment_UL; // 8 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered + // (NOTE 1) If DCI format 0_0 is monitored in common search space + // and if the number of information bits in the DCI format 0_0 prior to padding + // is larger than the payload size of the DCI format 1_0 monitored in common search space + // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 + // is reduced such that the size of DCI format 0_0 equals to the size of the DCI format 1_0 + uint16_t freq_dom_resource_assignment_DL; // 9 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: + uint8_t time_dom_resource_assignment ; // 10 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, + // where I the number of entries in the higher layer parameter pusch-AllocationList + uint8_t vrb_to_prb_mapping ; // 11 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0 + uint8_t prb_bundling_size_ind ; // 12 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] + uint8_t rate_matching_ind ; // 13 RATE_MATCHING_IND: 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set + uint8_t zp_csi_rs_trigger ; // 14 ZP_CSI_RS_TRIGGER: + uint8_t freq_hopping_flag ; // 15 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0 + uint8_t tb1_mcs ; // 16 TB1_MCS: + uint8_t tb1_ndi ; // 17 TB1_NDI: + uint8_t tb1_rv ; // 18 TB1_RV: + uint8_t tb2_mcs ; // 19 TB2_MCS: + uint8_t tb2_ndi ; // 20 TB2_NDI: + uint8_t tb2_rv ; // 21 TB2_RV: + uint8_t mcs ; // 22 MCS: + uint8_t ndi ; // 23 NDI: + uint8_t rv ; // 24 RV: + uint8_t harq_process_number ; // 25 HARQ_PROCESS_NUMBER: + uint8_t dai ; // 26 DAI: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI + // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI + // 0 otherwise + uint8_t first_dai ; // 27 FIRST_DAI: (1 or 2 bits) 1 bit for semi-static HARQ-ACK + uint8_t second_dai ; // 28 SECOND_DAI: (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks + uint8_t tpc_pusch ; // 29 TPC_PUSCH: + uint8_t tpc_pucch ; // 30 TPC_PUCCH: + uint8_t pucch_resource_ind ; // 31 PUCCH_RESOURCE_IND: + uint8_t pdsch_to_harq_feedback_time_ind ; // 32 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: + uint8_t short_message_ind ; // 33 SHORT_MESSAGE_IND: 1 bit if crc scrambled with P-RNTI + uint8_t srs_resource_ind ; // 34 SRS_RESOURCE_IND: + uint8_t precod_nbr_layers ; // 35 PRECOD_NBR_LAYERS: + uint8_t antenna_ports ; // 36 ANTENNA_PORTS: + uint8_t tci ; // 37 TCI: 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits + uint8_t srs_request ; // 38 SRS_REQUEST: + uint8_t tpc_cmd_number_format2_3 ; // 39 TPC_CMD_NUMBER_FORMAT2_3: + uint8_t csi_request ; // 40 CSI_REQUEST: + uint8_t cbgti ; // 41 CBGTI: 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH + uint8_t cbgfi ; // 42 CBGFI: 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator + uint8_t ptrs_dmrs ; // 43 PTRS_DMRS: + uint8_t beta_offset_ind ; // 44 BETA_OFFSET_IND: + uint8_t dmrs_seq_ini ; // 45 DMRS_SEQ_INI: 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding + // is larger than the number of bits for DCI format 0_0 before padding; 0 bit otherwise + uint8_t sul_ind_0_0 ; // 46 SUL_IND_0_0: + uint16_t padding ; // 47 PADDING: (Note 2) If DCI format 0_0 is monitored in common search space + // and if the number of information bits in the DCI format 0_0 prior to padding + // is less than the payload size of the DCI format 1_0 monitored in common search space + // zeros shall be appended to the DCI format 0_0 + // until the payload size equals that of the DCI format 1_0 + +}; +typedef struct NR_DCI_INFO_EXTRACTED NR_DCI_INFO_EXTRACTED_t; +#endif + diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c new file mode 100644 index 0000000000000000000000000000000000000000..03fb91e7fa3a7ce9c14cc6e05f8a5998381d87b2 --- /dev/null +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c @@ -0,0 +1,10080 @@ +/* + * 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 + */ + +/*! \file PHY/LTE_TRANSPORT/dci_tools_nr.c + * \brief PHY Support routines (eNB/UE) for filling PDSCH/PUSCH/DLSCH/ULSCH data structures based on DCI PDUs generated by eNB MAC scheduler. + * \author R. Knopp, A. Mico Pereperez + * \date 2018 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr + * \note + * \warning + */ +//#include "PHY/defs.h" +#include "PHY/defs_nr_UE.h" +//#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" +//#include "PHY/extern.h" +//#include "SCHED/defs.h" +#ifdef DEBUG_DCI_TOOLS +#include "PHY/vars.h" +#endif +#include "assertions.h" + + +//#define DEBUG_HARQ + +//#include "LAYER2/MAC/extern.h" +//#include "LAYER2/MAC/defs.h" +//#include "../openair2/LAYER2/MAC/extern.h" +//#include "../openair2/LAYER2/MAC/defs.h" + +//#define DEBUG_DCI +#define NR_PDCCH_DCI_TOOLS +#define NR_PDCCH_DCI_TOOLS_DEBUG + +#if 0 + +uint32_t localRIV2alloc_LUT6[32]; +uint32_t distRIV2alloc_even_LUT6[32]; +uint32_t distRIV2alloc_odd_LUT6[32]; +uint16_t RIV2nb_rb_LUT6[32]; +uint16_t RIV2first_rb_LUT6[32]; +uint16_t RIV_max6=0; + +uint32_t localRIV2alloc_LUT25[512]; +uint32_t distRIV2alloc_even_LUT25[512]; +uint32_t distRIV2alloc_odd_LUT25[512]; +uint16_t RIV2nb_rb_LUT25[512]; +uint16_t RIV2first_rb_LUT25[512]; +uint16_t RIV_max25=0; + + +uint32_t localRIV2alloc_LUT50_0[1600]; +uint32_t localRIV2alloc_LUT50_1[1600]; +uint32_t distRIV2alloc_gap0_even_LUT50_0[1600]; +uint32_t distRIV2alloc_gap0_odd_LUT50_0[1600]; +uint32_t distRIV2alloc_gap0_even_LUT50_1[1600]; +uint32_t distRIV2alloc_gap0_odd_LUT50_1[1600]; +uint32_t distRIV2alloc_gap1_even_LUT50_0[1600]; +uint32_t distRIV2alloc_gap1_odd_LUT50_0[1600]; +uint32_t distRIV2alloc_gap1_even_LUT50_1[1600]; +uint32_t distRIV2alloc_gap1_odd_LUT50_1[1600]; +uint16_t RIV2nb_rb_LUT50[1600]; +uint16_t RIV2first_rb_LUT50[1600]; +uint16_t RIV_max50=0; + +uint32_t localRIV2alloc_LUT100_0[6000]; +uint32_t localRIV2alloc_LUT100_1[6000]; +uint32_t localRIV2alloc_LUT100_2[6000]; +uint32_t localRIV2alloc_LUT100_3[6000]; +uint32_t distRIV2alloc_gap0_even_LUT100_0[6000]; +uint32_t distRIV2alloc_gap0_odd_LUT100_0[6000]; +uint32_t distRIV2alloc_gap0_even_LUT100_1[6000]; +uint32_t distRIV2alloc_gap0_odd_LUT100_1[6000]; +uint32_t distRIV2alloc_gap0_even_LUT100_2[6000]; +uint32_t distRIV2alloc_gap0_odd_LUT100_2[6000]; +uint32_t distRIV2alloc_gap0_even_LUT100_3[6000]; +uint32_t distRIV2alloc_gap0_odd_LUT100_3[6000]; +uint32_t distRIV2alloc_gap1_even_LUT100_0[6000]; +uint32_t distRIV2alloc_gap1_odd_LUT100_0[6000]; +uint32_t distRIV2alloc_gap1_even_LUT100_1[6000]; +uint32_t distRIV2alloc_gap1_odd_LUT100_1[6000]; +uint32_t distRIV2alloc_gap1_even_LUT100_2[6000]; +uint32_t distRIV2alloc_gap1_odd_LUT100_2[6000]; +uint32_t distRIV2alloc_gap1_even_LUT100_3[6000]; +uint32_t distRIV2alloc_gap1_odd_LUT100_3[6000]; +uint16_t RIV2nb_rb_LUT100[6000]; +uint16_t RIV2first_rb_LUT100[6000]; +uint16_t RIV_max100=0; + + +extern uint32_t current_dlsch_cqi; + +// Table 8.6.3-3 36.213 +uint16_t beta_cqi[16] = {0, //reserved + 0, //reserved + 9, //1.125 + 10, //1.250 + 11, //1.375 + 13, //1.625 + 14, //1.750 + 16, //2.000 + 18, //2.250 + 20, //2.500 + 23, //2.875 + 25, //3.125 + 28, //3.500 + 32, //4.000 + 40, //5.000 + 50 + }; //6.250 + +// Table 8.6.3-2 36.213 +uint16_t beta_ri[16] = {10, //1.250 + 13, //1.625 + 16, //2.000 + 20, //2.500 + 25, //3.125 + 32, //4.000 + 40, //5.000 + 50, //6.250 + 64, //8.000 + 80, //10.000 + 101, //12.625 + 127, //15.875 + 160, //20.000 + 0, //reserved + 0, //reserved + 0 + }; //reserved + +// Table 8.6.3-2 36.213 +uint16_t beta_ack[16] = {16, //2.000 + 20, //2.500 + 25, //3.125 + 32, //4.000 + 40, //5.000 + 50, //6.250 + 64, //8.000 + 80, //10.000 + 101, //12.625 + 127, //15.875 + 160, //20.000 + 248, //31.000 + 400, //50.000 + 640, //80.000 + 808 + };//126.00 + + +#endif +int8_t delta_PUSCH_abs[4] = {-4,-1,1,4}; +int8_t delta_PUSCH_acc[4] = {-1,0,1,3}; +int8_t *delta_PUCCH_lut = delta_PUSCH_acc; + +#if 0 +void conv_rballoc(uint8_t ra_header,uint32_t rb_alloc,uint32_t N_RB_DL,uint32_t *rb_alloc2) +{ + + uint32_t i,shift,subset; + rb_alloc2[0] = 0; + rb_alloc2[1] = 0; + rb_alloc2[2] = 0; + rb_alloc2[3] = 0; + + // printf("N_RB_DL %d, ra_header %d, rb_alloc %x\n",N_RB_DL,ra_header,rb_alloc); + + switch (N_RB_DL) { + + case 6: + rb_alloc2[0] = rb_alloc&0x3f; + break; + + case 25: + if (ra_header == 0) {// Type 0 Allocation + + for (i=12; i>0; i--) { + if ((rb_alloc&(1<<i)) != 0) + rb_alloc2[0] |= (3<<((2*(12-i)))); + + // printf("rb_alloc2 (type 0) %x\n",rb_alloc2); + } + + if ((rb_alloc&1) != 0) + rb_alloc2[0] |= (1<<24); + } else { + subset = rb_alloc&1; + shift = (rb_alloc>>1)&1; + + for (i=0; i<11; i++) { + if ((rb_alloc&(1<<(i+2))) != 0) + rb_alloc2[0] |= (1<<(2*i)); + + //printf("rb_alloc2 (type 1) %x\n",rb_alloc2); + } + + if ((shift == 0) && (subset == 1)) + rb_alloc2[0]<<=1; + else if ((shift == 1) && (subset == 0)) + rb_alloc2[0]<<=4; + else if ((shift == 1) && (subset == 1)) + rb_alloc2[0]<<=3; + } + + break; + + case 50: + if (ra_header == 0) {// Type 0 Allocation + + for (i=16; i>0; i--) { + if ((rb_alloc&(1<<i)) != 0) + rb_alloc2[(3*(16-i))>>5] |= (7<<((3*(16-i))%32)); + } + + /* + for (i=1;i<=16;i++) { + if ((rb_alloc&(1<<(16-i))) != 0) + rb_alloc2[(3*i)>>5] |= (7<<((3*i)%32)); + } + */ + // bit mask across + if ((rb_alloc2[0]>>31)==1) + rb_alloc2[1] |= 1; + + if ((rb_alloc&1) != 0) + rb_alloc2[1] |= (3<<16); + + /* + for (i=0;i<16;i++) { + if (((rb_alloc>>(16-i))&1) != 0) + rb_alloc2[(3*i)>>5] |= (7<<((3*i)%32)); + if ((i==10)&&((rb_alloc&(1<<6))!=0)) + rb_alloc2[1] = 1; + // printf("rb_alloc2[%d] (type 0) %x ((%x>>%d)&1=%d)\n",(3*i)>>5,rb_alloc2[(3*i)>>5],rb_alloc,i,(rb_alloc>>i)&1); + + } + // fill in 2 from last bit instead of 3 + if ((rb_alloc&1) != 0) + rb_alloc2[1] |= (3<<i); + // printf("rb_alloc2[%d] (type 0) %x ((%x>>%d)&1=%d)\n",(3*i)>>5,rb_alloc2[(3*i)>>5],rb_alloc,i,(rb_alloc>>i)&1); + */ + // printf("rb_alloc[1]=%x,rb_alloc[0]=%x\n",rb_alloc2[1],rb_alloc2[0]); + } else { + LOG_E(PHY,"resource type 1 not supported for N_RB_DL=50\n"); + // mac_xface->macphy_exit("resource type 1 not supported for N_RB_DL=100\n"); + /* + subset = rb_alloc&1; + shift = (rb_alloc>>1)&1; + for (i=0;i<11;i++) { + if ((rb_alloc&(1<<(i+2))) != 0) + rb_alloc2 |= (1<<(2*i)); + // printf("rb_alloc2 (type 1) %x\n",rb_alloc2); + } + if ((shift == 0) && (subset == 1)) + rb_alloc2<<=1; + else if ((shift == 1) && (subset == 0)) + rb_alloc2<<=4; + else if ((shift == 1) && (subset == 1)) + rb_alloc2<<=3; + */ + } + + break; + + case 100: + if (ra_header == 0) {// Type 0 Allocation + for (i=0; i<25; i++) { + if ((rb_alloc&(1<<(24-i))) != 0) + rb_alloc2[(4*i)>>5] |= (0xf<<((4*i)%32)); + + // printf("rb_alloc2[%d] (type 0) %x (%d)\n",(4*i)>>5,rb_alloc2[(4*i)>>5],rb_alloc&(1<<i)); + } + } else { + LOG_E(PHY,"resource type 1 not supported for N_RB_DL=100\n"); + // mac_xface->macphy_exit("resource type 1 not supported for N_RB_DL=100\n"); + /* + subset = rb_alloc&1; + shift = (rb_alloc>>1)&1; + for (i=0;i<11;i++) { + if ((rb_alloc&(1<<(i+2))) != 0) + rb_alloc2 |= (1<<(2*i)); + // printf("rb_alloc2 (type 1) %x\n",rb_alloc2); + } + if ((shift == 0) && (subset == 1)) + rb_alloc2<<=1; + else if ((shift == 1) && (subset == 0)) + rb_alloc2<<=4; + else if ((shift == 1) && (subset == 1)) + rb_alloc2<<=3; + */ + } + + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", N_RB_DL); + DevParam (N_RB_DL, 0, 0); + break; + } + +} + + + +uint32_t conv_nprb(uint8_t ra_header,uint32_t rb_alloc,int N_RB_DL) +{ + + uint32_t nprb=0,i; + + switch (N_RB_DL) { + case 6: + for (i=0; i<6; i++) { + if ((rb_alloc&(1<<i)) != 0) + nprb += 1; + } + + break; + + case 25: + if (ra_header == 0) {// Type 0 Allocation + + for (i=12; i>0; i--) { + if ((rb_alloc&(1<<i)) != 0) + nprb += 2; + } + + if ((rb_alloc&1) != 0) + nprb += 1; + } else { + for (i=0; i<11; i++) { + if ((rb_alloc&(1<<(i+2))) != 0) + nprb += 1; + } + } + + break; + + case 50: + if (ra_header == 0) {// Type 0 Allocation + + for (i=0; i<16; i++) { + if ((rb_alloc&(1<<(16-i))) != 0) + nprb += 3; + } + + if ((rb_alloc&1) != 0) + nprb += 2; + + } else { + for (i=0; i<17; i++) { + if ((rb_alloc&(1<<(i+2))) != 0) + nprb += 1; + } + } + + break; + + case 100: + if (ra_header == 0) {// Type 0 Allocation + + for (i=0; i<25; i++) { + if ((rb_alloc&(1<<(24-i))) != 0) + nprb += 4; + } + } else { + for (i=0; i<25; i++) { + if ((rb_alloc&(1<<(i+2))) != 0) + nprb += 1; + } + } + + break; + + default: + LOG_E(PHY,"Invalide N_RB_DL %d\n", N_RB_DL); + DevParam (N_RB_DL, 0, 0); + break; + } + + return(nprb); +} + +uint16_t computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs) +{ + + uint16_t RIV; + + if (Lcrbs<=(1+(N_RB_DL>>1))) + RIV = (N_RB_DL*(Lcrbs-1)) + RBstart; + else + RIV = (N_RB_DL*(N_RB_DL+1-Lcrbs)) + (N_RB_DL-1-RBstart); + + return(RIV); +} + +// Convert a DCI Format 1C RIV to a Format 1A RIV +// This extracts the start and length in PRBs from the 1C rballoc and +// recomputes the RIV as if it were the 1A rballoc + +uint32_t conv_1C_RIV(int32_t rballoc,uint32_t N_RB_DL) { + + int NpDLVRB,N_RB_step,LpCRBsm1,RBpstart; + + switch (N_RB_DL) { + + case 6: // N_RB_step = 2, NDLVRB = 6, NpDLVRB = 3 + NpDLVRB = 3; + N_RB_step = 2; + break; + case 25: // N_RB_step = 2, NDLVRB = 24, NpDLVRB = 12 + NpDLVRB = 12; + N_RB_step = 2; + break; + case 50: // N_RB_step = 4, NDLVRB = 46, NpDLVRB = 11 + NpDLVRB = 11; + N_RB_step = 4; + break; + case 100: // N_RB_step = 4, NDLVRB = 96, NpDLVRB = 24 + NpDLVRB = 24; + N_RB_step = 4; + break; + default: + NpDLVRB = 24; + N_RB_step = 4; + break; + } + + // This is the 1C part from 7.1.6.3 in 36.213 + LpCRBsm1 = rballoc/NpDLVRB; + // printf("LpCRBs = %d\n",LpCRBsm1+1); + + if (LpCRBsm1 <= (NpDLVRB/2)) { + RBpstart = rballoc % NpDLVRB; + } + else { + LpCRBsm1 = NpDLVRB-LpCRBsm1; + RBpstart = NpDLVRB-(rballoc%NpDLVRB); + } + // printf("RBpstart %d\n",RBpstart); + return(computeRIV(N_RB_DL,N_RB_step*RBpstart,N_RB_step*(LpCRBsm1+1))); + +} + +uint32_t get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap) { + + int offset; + + switch (N_RB_DL) { + + case 6: + // N_RB_DL = tildeN_RB_DL = 6 + // Ngap = 4 , P=1, Nrow = 2, Nnull = 2 + + switch (vrb) { + case 0: // even: 0->0, 1->2, odd: 0->3, 1->5 + case 1: + return ((3*odd_slot) + 2*(vrb&3))%6; + break; + case 2: // even: 2->3, 3->5, odd: 2->0, 3->2 + case 3: + return ((3*odd_slot) + 2*(vrb&3) + 5)%6; + break; + case 4: // even: 4->1, odd: 4->4 + return ((3*odd_slot) + 1)%6; + case 5: // even: 5->4, odd: 5->1 + return ((3*odd_slot) + 4)%6; + break; + } + break; + + case 15: + if (vrb<12) { + if ((vrb&3) < 2) // even: 0->0, 1->4, 4->1, 5->5, 8->2, 9->6 odd: 0->7, 1->11 + return(((7*odd_slot) + 4*(vrb&3) + (vrb>>2))%14) + 14*(vrb/14); + else if (vrb < 12) // even: 2->7, 3->11, 6->8, 7->12, 10->9, 11->13 + return (((7*odd_slot) + 4*(vrb&3) + (vrb>>2) +13 )%14) + 14*(vrb/14); + } + if (vrb==12) + return (3+(7*odd_slot)) % 14; + if (vrb==13) + return (10+(7*odd_slot)) % 14; + return 14; + break; + + case 25: + return (((12*odd_slot) + 6*(vrb&3) + (vrb>>2))%24) + 24*(vrb/24); + break; + + case 50: // P=3 + if (Ngap==0) { + // Nrow=12,Nnull=2,NVRBDL=46,Ngap1= 27 + if (vrb>=23) + offset=4; + else + offset=0; + if (vrb<44) { + if ((vrb&3)>=2) + return offset+((23*odd_slot) + 12*(vrb&3) + (vrb>>2) + 45)%46; + else + return offset+((23*odd_slot) + 12*(vrb&3) + (vrb>>2))%46; + } + if (vrb==44) // even: 44->11, odd: 45->34 + return offset+((23*odd_slot) + 22-12+1); + if (vrb==45) // even: 45->10, odd: 45->33 + return offset+((23*odd_slot) + 22+12); + if (vrb==46) + return offset+46+((23*odd_slot) + 23-12+1) % 46; + if (vrb==47) + return offset+46+((23*odd_slot) + 23+12) % 46; + if (vrb==48) + return offset+46+((23*odd_slot) + 23-12+1) % 46; + if (vrb==49) + return offset+46+((23*odd_slot) + 23+12) % 46; + } + else { + // Nrow=6,Nnull=6,NVRBDL=18,Ngap1= 27 + if (vrb>=9) + offset=18; + else + offset=0; + + if (vrb<12) { + if ((vrb&3)>=2) + return offset+((9*odd_slot) + 6*(vrb&3) + (vrb>>2) + 17)%18; + else + return offset+((9*odd_slot) + 6*(vrb&3) + (vrb>>2))%18; + } + else { + return offset+((9*odd_slot) + 12*(vrb&1)+(vrb>>1) )%18 + 18*(vrb/18); + } + } + break; + case 75: + // Ngap1 = 32, NVRBRL=64, P=4, Nrow= 16, Nnull=0 + if (Ngap ==0) { + return ((32*odd_slot) + 16*(vrb&3) + (vrb>>2))%64 + (vrb/64); + } else { + // Ngap2 = 16, NVRBDL=32, Nrow=8, Nnull=0 + return ((16*odd_slot) + 8*(vrb&3) + (vrb>>2))%32 + (vrb/32); + } + break; + case 100: + // Ngap1 = 48, NVRBDL=96, Nrow=24, Nnull=0 + if (Ngap ==0) { + return ((48*odd_slot) + 24*(vrb&3) + (vrb>>2))%96 + (vrb/96); + } else { + // Ngap2 = 16, NVRBDL=32, Nrow=8, Nnull=0 + return ((16*odd_slot) + 8*(vrb&3) + (vrb>>2))%32 + (vrb/32); + } + break; + default: + LOG_E(PHY,"Unknown N_RB_DL %d\n",N_RB_DL); + return 0; + } + return 0; + +} + + +void generate_RIV_tables() +{ + + // 6RBs localized RIV + uint8_t Lcrbs,RBstart; + uint16_t RIV; + uint32_t alloc0,allocdist0_0_even,allocdist0_0_odd,allocdist0_1_even,allocdist0_1_odd; + uint32_t alloc1,allocdist1_0_even,allocdist1_0_odd,allocdist1_1_even,allocdist1_1_odd; + uint32_t alloc2,allocdist2_0_even,allocdist2_0_odd,allocdist2_1_even,allocdist2_1_odd; + uint32_t alloc3,allocdist3_0_even,allocdist3_0_odd,allocdist3_1_even,allocdist3_1_odd; + uint32_t nVRB,nVRB_even_dist,nVRB_odd_dist; + + for (RBstart=0; RBstart<6; RBstart++) { + alloc0 = 0; + allocdist0_0_even = 0; + allocdist0_0_odd = 0; + for (Lcrbs=1; Lcrbs<=(6-RBstart); Lcrbs++) { + //printf("RBstart %d, len %d --> ",RBstart,Lcrbs); + nVRB = Lcrbs-1+RBstart; + alloc0 |= (1<<nVRB); + allocdist0_0_even |= (1<<get_prb(6,0,nVRB,0)); + allocdist0_0_odd |= (1<<get_prb(6,1,nVRB,0)); + RIV=computeRIV(6,RBstart,Lcrbs); + + if (RIV>RIV_max6) + RIV_max6 = RIV; + + // printf("RIV %d (%d) : first_rb %d NBRB %d\n",RIV,localRIV2alloc_LUT25[RIV],RBstart,Lcrbs); + localRIV2alloc_LUT6[RIV] = alloc0; + distRIV2alloc_even_LUT6[RIV] = allocdist0_0_even; + distRIV2alloc_odd_LUT6[RIV] = allocdist0_0_odd; + RIV2nb_rb_LUT6[RIV] = Lcrbs; + RIV2first_rb_LUT6[RIV] = RBstart; + } + } + + + for (RBstart=0; RBstart<25; RBstart++) { + alloc0 = 0; + allocdist0_0_even = 0; + allocdist0_0_odd = 0; + for (Lcrbs=1; Lcrbs<=(25-RBstart); Lcrbs++) { + nVRB = Lcrbs-1+RBstart; + //printf("RBstart %d, len %d --> ",RBstart,Lcrbs); + alloc0 |= (1<<nVRB); + allocdist0_0_even |= (1<<get_prb(25,0,nVRB,0)); + allocdist0_0_odd |= (1<<get_prb(25,1,nVRB,0)); + + //printf("alloc 0 %x, allocdist0_even %x, allocdist0_odd %x\n",alloc0,allocdist0_0_even,allocdist0_0_odd); + RIV=computeRIV(25,RBstart,Lcrbs); + + if (RIV>RIV_max25) + RIV_max25 = RIV;; + + + localRIV2alloc_LUT25[RIV] = alloc0; + distRIV2alloc_even_LUT25[RIV] = allocdist0_0_even; + distRIV2alloc_odd_LUT25[RIV] = allocdist0_0_odd; + RIV2nb_rb_LUT25[RIV] = Lcrbs; + RIV2first_rb_LUT25[RIV] = RBstart; + } + } + + + for (RBstart=0; RBstart<50; RBstart++) { + alloc0 = 0; + alloc1 = 0; + allocdist0_0_even=0; + allocdist1_0_even=0; + allocdist0_0_odd=0; + allocdist1_0_odd=0; + allocdist0_1_even=0; + allocdist1_1_even=0; + allocdist0_1_odd=0; + allocdist1_1_odd=0; + + for (Lcrbs=1; Lcrbs<=(50-RBstart); Lcrbs++) { + + nVRB = Lcrbs-1+RBstart; + + + if (nVRB<32) + alloc0 |= (1<<nVRB); + else + alloc1 |= (1<<(nVRB-32)); + + // Distributed Gap1, even slot + nVRB_even_dist = get_prb(50,0,nVRB,0); + if (nVRB_even_dist<32) + allocdist0_0_even |= (1<<nVRB_even_dist); + else + allocdist1_0_even |= (1<<(nVRB_even_dist-32)); + + // Distributed Gap1, odd slot + nVRB_odd_dist = get_prb(50,1,nVRB,0); + if (nVRB_odd_dist<32) + allocdist0_0_odd |= (1<<nVRB_odd_dist); + else + allocdist1_0_odd |= (1<<(nVRB_odd_dist-32)); + + // Distributed Gap2, even slot + nVRB_even_dist = get_prb(50,0,nVRB,1); + if (nVRB_even_dist<32) + allocdist0_1_even |= (1<<nVRB_even_dist); + else + allocdist1_1_even |= (1<<(nVRB_even_dist-32)); + + // Distributed Gap2, odd slot + nVRB_odd_dist = get_prb(50,1,nVRB,1); + if (nVRB_odd_dist<32) + allocdist0_1_odd |= (1<<nVRB_odd_dist); + else + allocdist1_1_odd |= (1<<(nVRB_odd_dist-32)); + + RIV=computeRIV(50,RBstart,Lcrbs); + + if (RIV>RIV_max50) + RIV_max50 = RIV; + + // printf("RIV %d : first_rb %d NBRB %d\n",RIV,RBstart,Lcrbs); + localRIV2alloc_LUT50_0[RIV] = alloc0; + localRIV2alloc_LUT50_1[RIV] = alloc1; + distRIV2alloc_gap0_even_LUT50_0[RIV] = allocdist0_0_even; + distRIV2alloc_gap0_even_LUT50_1[RIV] = allocdist1_0_even; + distRIV2alloc_gap0_odd_LUT50_0[RIV] = allocdist0_0_odd; + distRIV2alloc_gap0_odd_LUT50_1[RIV] = allocdist1_0_odd; + distRIV2alloc_gap1_even_LUT50_0[RIV] = allocdist0_1_even; + distRIV2alloc_gap1_even_LUT50_1[RIV] = allocdist1_1_even; + distRIV2alloc_gap1_odd_LUT50_0[RIV] = allocdist0_1_odd; + distRIV2alloc_gap1_odd_LUT50_1[RIV] = allocdist1_1_odd; + RIV2nb_rb_LUT50[RIV] = Lcrbs; + RIV2first_rb_LUT50[RIV] = RBstart; + } + } + + + for (RBstart=0; RBstart<100; RBstart++) { + alloc0 = 0; + alloc1 = 0; + alloc2 = 0; + alloc3 = 0; + allocdist0_0_even=0; + allocdist1_0_even=0; + allocdist2_0_even=0; + allocdist3_0_even=0; + allocdist0_0_odd=0; + allocdist1_0_odd=0; + allocdist2_0_odd=0; + allocdist3_0_odd=0; + allocdist0_1_even=0; + allocdist1_1_even=0; + allocdist2_1_even=0; + allocdist3_1_even=0; + allocdist0_1_odd=0; + allocdist1_1_odd=0; + allocdist2_1_odd=0; + allocdist3_1_odd=0; + + for (Lcrbs=1; Lcrbs<=(100-RBstart); Lcrbs++) { + + nVRB = Lcrbs-1+RBstart; + + if (nVRB<32) + alloc0 |= (1<<nVRB); + else if (nVRB<64) + alloc1 |= (1<<(nVRB-32)); + else if (nVRB<96) + alloc2 |= (1<<(nVRB-64)); + else + alloc3 |= (1<<(nVRB-96)); + + // Distributed Gap1, even slot + nVRB_even_dist = get_prb(100,0,nVRB,0); + +// if ((RBstart==0) && (Lcrbs<=8)) +// printf("nVRB %d => nVRB_even_dist %d\n",nVRB,nVRB_even_dist); + + + if (nVRB_even_dist<32) + allocdist0_0_even |= (1<<nVRB_even_dist); + else if (nVRB_even_dist<64) + allocdist1_0_even |= (1<<(nVRB_even_dist-32)); + else if (nVRB_even_dist<96) + allocdist2_0_even |= (1<<(nVRB_even_dist-64)); + else + allocdist3_0_even |= (1<<(nVRB_even_dist-96)); +/* if ((RBstart==0) && (Lcrbs<=8)) + printf("rballoc =>(%08x.%08x.%08x.%08x)\n", + allocdist0_0_even, + allocdist1_0_even, + allocdist2_0_even, + allocdist3_0_even + ); +*/ + // Distributed Gap1, odd slot + nVRB_odd_dist = get_prb(100,1,nVRB,0); + if (nVRB_odd_dist<32) + allocdist0_0_odd |= (1<<nVRB_odd_dist); + else if (nVRB_odd_dist<64) + allocdist1_0_odd |= (1<<(nVRB_odd_dist-32)); + else if (nVRB_odd_dist<96) + allocdist2_0_odd |= (1<<(nVRB_odd_dist-64)); + else + allocdist3_0_odd |= (1<<(nVRB_odd_dist-96)); + + + // Distributed Gap2, even slot + nVRB_even_dist = get_prb(100,0,nVRB,1); + if (nVRB_even_dist<32) + allocdist0_1_even |= (1<<nVRB_even_dist); + else if (nVRB_even_dist<64) + allocdist1_1_even |= (1<<(nVRB_even_dist-32)); + else if (nVRB_even_dist<96) + allocdist2_1_even |= (1<<(nVRB_even_dist-64)); + else + allocdist3_1_even |= (1<<(nVRB_even_dist-96)); + + + // Distributed Gap2, odd slot + nVRB_odd_dist = get_prb(100,1,nVRB,1); + if (nVRB_odd_dist<32) + allocdist0_1_odd |= (1<<nVRB_odd_dist); + else if (nVRB_odd_dist<64) + allocdist1_1_odd |= (1<<(nVRB_odd_dist-32)); + else if (nVRB_odd_dist<96) + allocdist2_1_odd |= (1<<(nVRB_odd_dist-64)); + else + allocdist3_1_odd |= (1<<(nVRB_odd_dist-96)); + + + RIV=computeRIV(100,RBstart,Lcrbs); + + if (RIV>RIV_max100) + RIV_max100 = RIV; + + // printf("RIV %d : first_rb %d NBRB %d\n",RIV,RBstart,Lcrbs); + localRIV2alloc_LUT100_0[RIV] = alloc0; + localRIV2alloc_LUT100_1[RIV] = alloc1; + localRIV2alloc_LUT100_2[RIV] = alloc2; + localRIV2alloc_LUT100_3[RIV] = alloc3; + distRIV2alloc_gap0_even_LUT100_0[RIV] = allocdist0_0_even; + distRIV2alloc_gap0_even_LUT100_1[RIV] = allocdist1_0_even; + distRIV2alloc_gap0_even_LUT100_2[RIV] = allocdist2_0_even; + distRIV2alloc_gap0_even_LUT100_3[RIV] = allocdist3_0_even; + distRIV2alloc_gap0_odd_LUT100_0[RIV] = allocdist0_0_odd; + distRIV2alloc_gap0_odd_LUT100_1[RIV] = allocdist1_0_odd; + distRIV2alloc_gap0_odd_LUT100_2[RIV] = allocdist2_0_odd; + distRIV2alloc_gap0_odd_LUT100_3[RIV] = allocdist3_0_odd; + distRIV2alloc_gap1_even_LUT100_0[RIV] = allocdist0_1_even; + distRIV2alloc_gap1_even_LUT100_1[RIV] = allocdist1_1_even; + distRIV2alloc_gap1_even_LUT100_2[RIV] = allocdist2_1_even; + distRIV2alloc_gap1_even_LUT100_3[RIV] = allocdist3_1_even; + distRIV2alloc_gap1_odd_LUT100_0[RIV] = allocdist0_1_odd; + distRIV2alloc_gap1_odd_LUT100_1[RIV] = allocdist1_1_odd; + distRIV2alloc_gap1_odd_LUT100_2[RIV] = allocdist2_1_odd; + distRIV2alloc_gap1_odd_LUT100_3[RIV] = allocdist3_1_odd; + + RIV2nb_rb_LUT100[RIV] = Lcrbs; + RIV2first_rb_LUT100[RIV] = RBstart; + } + } +} + +// Ngap = 3, N_VRB_DL=6, P=1, N_row=2, N_null=4*2-6=2 +// permutation for even slots : +// n_PRB'(0,2,4) = (0,1,2), n_PRB'(1,3,5) = (4,5,6) +// n_PRB''(0,1,2,3) = (0,2,4,6) +// => n_tilde_PRB(5) = (4) +// n_tilde_PRB(4) = (1) +// n_tilde_PRB(2,3) = (3,5) +// n_tilde_PRB(0,1) = (0,2) + + + +uint32_t get_rballoc(vrb_t vrb_type,uint16_t rb_alloc_dci) +{ + + return(localRIV2alloc_LUT25[rb_alloc_dci]); + +} + +uint8_t get_transmission_mode(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti) +{ + unsigned char UE_id; + + // find the UE_index corresponding to rnti + UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]); + DevAssert( UE_id != (unsigned char)-1 ); + + return(PHY_vars_eNB_g[Mod_id][CC_id]->transmission_mode[UE_id]); +} + +int generate_eNB_dlsch_params_from_dci(int frame, + uint8_t subframe, + void *dci_pdu, + uint16_t rnti, + DCI_format_t dci_format, + LTE_eNB_DLSCH_t **dlsch, + NR_DL_FRAME_PARMS *frame_parms, + PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint16_t DL_pmi_single, + uint8_t beamforming_mode) +{ + + uint8_t harq_pid = UINT8_MAX; + uint32_t rballoc = UINT32_MAX; + uint32_t RIV_max = 0; + uint8_t NPRB,tbswap,tpmi=0; + LTE_eNB_DLSCH_t *dlsch0=NULL,*dlsch1=NULL; + uint8_t frame_type=frame_parms->frame_type; + uint8_t vrb_type=0; + uint8_t mcs=0,mcs1=0,mcs2=0; + uint8_t I_mcs = 0; + uint8_t rv=0,rv1=0,rv2=0; + uint8_t rah=0; + uint8_t TPC=0; + uint8_t TB0_active=0,TB1_active=0; + LTE_DL_eNB_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL; + + // printf("Generate eNB DCI, format %d, rnti %x (pdu %p)\n",dci_format,rnti,dci_pdu); + + switch (dci_format) { + + case format0: + return(-1); + break; + + case format1A: // This is DLSCH allocation for control traffic + + + + dlsch[0]->subframe_tx[subframe] = 1; + + + switch (frame_parms->N_RB_DL) { + case 6: + if (frame_type == TDD) { + vrb_type = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rballoc; + rv = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rv; + TPC = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid; + + // printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); + } else { + vrb_type = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rv; + TPC = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->harq_pid; + + // printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); + } + + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch0_harq->codeword=0; + + if (vrb_type==LOCALIZED) { + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT6[rballoc]; + } + else { + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); + } + dlsch0_harq->vrb_type = vrb_type; + dlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rballoc];//NPRB; + RIV_max = RIV_max6; + + + break; + + case 25: + if (frame_type == TDD) { + vrb_type = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rballoc; + rv = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rv; + TPC = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid; + + // printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); + } else { + vrb_type = ((DCI1A_5MHz_FDD_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_5MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_5MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1A_5MHz_FDD_t *)dci_pdu)->rv; + TPC = ((DCI1A_5MHz_FDD_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_5MHz_FDD_t *)dci_pdu)->harq_pid; + + // printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); + } + + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + + + if (vrb_type==LOCALIZED) { + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT25[rballoc]; + } + else { + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); + } + dlsch0_harq->vrb_type = vrb_type; + dlsch0_harq->nb_rb = RIV2nb_rb_LUT25[rballoc];//NPRB; + RIV_max = RIV_max25; + break; + + case 50: + if (frame_type == TDD) { + vrb_type = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rballoc; + rv = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rv; + TPC = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->harq_pid; + + // printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); + } else { + vrb_type = ((DCI1A_10MHz_FDD_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_10MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_10MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1A_10MHz_FDD_t *)dci_pdu)->rv; + TPC = ((DCI1A_10MHz_FDD_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_10MHz_FDD_t *)dci_pdu)->harq_pid; + //printf("FDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC); + } + + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + if (vrb_type==LOCALIZED) { + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT50_0[rballoc]; + dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT50_1[rballoc]; + } + else { + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); + } + + + dlsch0_harq->vrb_type = vrb_type; + dlsch0_harq->nb_rb = RIV2nb_rb_LUT50[rballoc];//NPRB; + RIV_max = RIV_max50; + break; + + case 100: + if (frame_type == TDD) { + vrb_type = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rballoc; + rv = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rv; + TPC = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->harq_pid; + // printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); + } else { + vrb_type = ((DCI1A_20MHz_FDD_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_20MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_20MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1A_20MHz_FDD_t *)dci_pdu)->rv; + TPC = ((DCI1A_20MHz_FDD_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_20MHz_FDD_t *)dci_pdu)->harq_pid; + // printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); + } + + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + + dlsch0_harq->vrb_type = vrb_type; + if (vrb_type==LOCALIZED) { + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT100_0[rballoc]; + dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT100_1[rballoc]; + dlsch0_harq->rb_alloc[2] = localRIV2alloc_LUT100_2[rballoc]; + dlsch0_harq->rb_alloc[3] = localRIV2alloc_LUT100_3[rballoc]; + } + else { + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); + } + + + + dlsch0_harq->nb_rb = RIV2nb_rb_LUT100[rballoc];//NPRB; + RIV_max = RIV_max100; + break; + + default: + LOG_E(PHY,"Invalid N_RB_D %dL\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + + // harq_pid field is reserved + if ((rnti==si_rnti) || (rnti==ra_rnti) || (rnti==p_rnti)) { // + harq_pid=0; + // see 36-212 V8.6.0 p. 45 + NPRB = (TPC&1)+2; + // 36-213 sec.7.1.7.2 p.26 + I_mcs = mcs; + } else { + if (harq_pid>=8) { + LOG_E(PHY,"ERROR: Format 1A: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + if (rballoc>RIV_max) { + LOG_E(PHY,"ERROR: Format 1A: rb_alloc (%x) > RIV_max (%x)\n",rballoc,RIV_max); + return(-1); + } + + NPRB = dlsch0_harq->nb_rb; + I_mcs = get_I_TBS(mcs); + } + + if (NPRB==0) + return(-1); + + //printf("NPRB %d, nb_rb %d, ndi %d\n",NPRB,dlsch0_harq->nb_rb,ndi); + dlsch0_harq->rvidx = rv; + + dlsch0_harq->Nl = 1; + //dlsch0_harq->layer_index = 0; + + dlsch0_harq->mimo_mode = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI; + /* + if ((rnti!=si_rnti)&&(rnti!=ra_rnti)&&(rnti!=p_rnti)) { //handle toggling for C-RNTI + if (dlsch0_harq->first_tx == 1) { + LOG_D(PHY,"First TX for TC-RNTI %x, clearing first_tx flag\n",rnti); + dlsch0_harq->first_tx=0; + dlsch0_harq->Ndi = 1; + } + else { + if (ndi == dlsch0_harq->DCINdi) + dlsch0_harq->Ndi = 0; + else + dlsch0_harq->Ndi = 1; + } + + dlsch0_harq->DCINdi=ndi; + } + else { + dlsch0_harq->Ndi = 1; + } + */ + dlsch0_harq->dl_power_off = 1; + + + + dlsch0_harq->mcs = mcs; + dlsch0_harq->TBS = TBStable[I_mcs][NPRB-1]; + + dlsch[0]->current_harq_pid = harq_pid; + dlsch[0]->harq_ids[subframe] = harq_pid; + + dlsch[0]->active = 1; + dlsch0 = dlsch[0]; + + dlsch[0]->rnti = rnti; + + dlsch[0]->harq_ids[subframe] = harq_pid; + + if (dlsch0_harq->round == 0) + dlsch0_harq->status = ACTIVE; + + break; + + case format1: + + switch (frame_parms->N_RB_DL) { + + case 6: + if (frame_type == TDD) { + mcs = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rah; + rv = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rv; + harq_pid = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->mcs; + rah = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rah; + rballoc = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rv; + harq_pid = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 25: + + if (frame_type == TDD) { + mcs = ((DCI1_5MHz_TDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1_5MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI1_5MHz_TDD_t *)dci_pdu)->rah; + rv = ((DCI1_5MHz_TDD_t *)dci_pdu)->rv; + harq_pid = ((DCI1_5MHz_TDD_t *)dci_pdu)->harq_pid; + LOG_D(PHY,"eNB: subframe %d UE %x, Format1 DCI: ndi %d, harq_pid %d\n",subframe,rnti,((DCI1_5MHz_TDD_t *)dci_pdu)->ndi,harq_pid); + } else { + mcs = ((DCI1_5MHz_FDD_t *)dci_pdu)->mcs; + rah = ((DCI1_5MHz_FDD_t *)dci_pdu)->rah; + rballoc = ((DCI1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1_5MHz_FDD_t *)dci_pdu)->rv; + harq_pid = ((DCI1_5MHz_FDD_t *)dci_pdu)->harq_pid; + LOG_D(PHY,"eNB: subframe %d UE %x, Format1 DCI: ndi %d, harq_pid %d\n",subframe,rnti,((DCI1_5MHz_FDD_t *)dci_pdu)->ndi,harq_pid); + + } + + break; + + case 50: + if (frame_type == TDD) { + mcs = ((DCI1_10MHz_TDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1_10MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI1_10MHz_TDD_t *)dci_pdu)->rah; + rv = ((DCI1_10MHz_TDD_t *)dci_pdu)->rv; + harq_pid = ((DCI1_10MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs = ((DCI1_10MHz_FDD_t *)dci_pdu)->mcs; + rah = ((DCI1_10MHz_FDD_t *)dci_pdu)->rah; + rballoc = ((DCI1_10MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1_10MHz_FDD_t *)dci_pdu)->rv; + harq_pid = ((DCI1_10MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 100: + if (frame_type == TDD) { + mcs = ((DCI1_20MHz_TDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1_20MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI1_20MHz_TDD_t *)dci_pdu)->rah; + rv = ((DCI1_20MHz_TDD_t *)dci_pdu)->rv; + harq_pid = ((DCI1_20MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs = ((DCI1_20MHz_FDD_t *)dci_pdu)->mcs; + rah = ((DCI1_20MHz_FDD_t *)dci_pdu)->rah; + rballoc = ((DCI1_20MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1_20MHz_FDD_t *)dci_pdu)->rv; + harq_pid = ((DCI1_20MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + } + + if (harq_pid>=8) { + LOG_E(PHY,"ERROR: Format 1: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch0_harq->codeword=0; + + // printf("DCI: Setting subframe_tx for subframe %d\n",subframe); + dlsch[0]->subframe_tx[subframe] = 1; + + conv_rballoc(rah, + rballoc,frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc); + + dlsch0_harq->nb_rb = conv_nprb(rah, + rballoc, + frame_parms->N_RB_DL); + + NPRB = dlsch0_harq->nb_rb; + + + if (NPRB==0) + return(-1); + + + dlsch0_harq->rvidx = rv; + + dlsch0_harq->Nl = 1; + // dlsch[0]->layer_index = 0; + if (beamforming_mode == 0) + dlsch0_harq->mimo_mode = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI; + else if (beamforming_mode == 7) + dlsch0_harq->mimo_mode = TM7; + else + LOG_E(PHY,"Invalid beamforming mode %dL\n", beamforming_mode); + + dlsch0_harq->dl_power_off = 1; + /* + if (dlsch[0]->harq_processes[harq_pid]->first_tx == 1) { + LOG_D(PHY,"First TX for C-RNTI %x, clearing first_tx flag, shouldn't happen!\n",rnti); + dlsch[0]->harq_processes[harq_pid]->first_tx=0; + dlsch[0]->harq_processes[harq_pid]->Ndi = 1; + } + else { + LOG_D(PHY,"Checking for Toggled Ndi for C-RNTI %x, old value %d, DCINdi %d\n",rnti,dlsch[0]->harq_processes[harq_pid]->DCINdi,ndi); + if (ndi == dlsch[0]->harq_processes[harq_pid]->DCINdi) + dlsch[0]->harq_processes[harq_pid]->Ndi = 0; + else + dlsch[0]->harq_processes[harq_pid]->Ndi = 1; + } + dlsch[0]->harq_processes[harq_pid]->DCINdi=ndi; + */ + + dlsch[0]->active = 1; + + + + if (dlsch0_harq->round == 0) { + dlsch0_harq->status = ACTIVE; + // MCS and TBS don't change across HARQ rounds + dlsch0_harq->mcs = mcs; + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][NPRB-1]; + + } + + dlsch[0]->current_harq_pid = harq_pid; + dlsch[0]->harq_ids[subframe] = harq_pid; + + + + dlsch0 = dlsch[0]; + + dlsch[0]->rnti = rnti; + + + break; + + case format2: // DL Scheduling assignment for MIMO including closed loop spatial multiplexing + + switch (frame_parms->N_RB_DL) { + + case 6: + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tpmi; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->tpmi; + } + } else { + LOG_E(PHY,"eNB: subframe %d UE %x, Format2 DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB); + } + + break; + + case 25: + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tpmi; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->tpmi; + } + } else { + LOG_E(PHY,"eNB: subframe %d UE %x, Format2 DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB); + } + + break; + + case 50: + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tpmi; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->tpmi; + } + } else { + LOG_E(PHY,"eNB: subframe %d UE %x, Format2 DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB); + } + + break; + + case 100: + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tpmi; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->tpmi; + } + } else { + LOG_E(PHY,"eNB: subframe %d UE %x, Format2 DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB); + } + + break; + } + + if (harq_pid>=8) { + LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + + // Flip the TB to codeword mapping as described in 5.3.3.1.5 of 36-212 V11.3.0 + // note that we must set tbswap=0 in eNB scheduler if one TB is deactivated + TB0_active = 1; + TB1_active = 1; + + if ((rv1 == 1) && (mcs1 == 0)) { + TB0_active=0; + } + if ((rv2 == 1) && (mcs2 == 0)) { + TB1_active=0; + } +#ifdef DEBUG_HARQ + printf(" eNOdeB RV0 = %d, RV1 = %d. MCS0 = %d, MCS1=%d\n", rv1, rv2, mcs1, mcs2); +#endif + if (TB0_active && TB1_active && tbswap==0) { + dlsch0=dlsch[0]; + dlsch1=dlsch[1]; + dlsch0->active = 1; + dlsch1->active = 1; + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + dlsch0_harq->mcs = mcs1; + dlsch1_harq->mcs = mcs2; + dlsch0_harq->rvidx = rv1; + dlsch1_harq->rvidx = rv2; + dlsch0_harq->status = ACTIVE; + dlsch1_harq->status = ACTIVE; + dlsch0_harq->codeword=0; + dlsch1_harq->codeword=1; +#ifdef DEBUG_HARQ + printf("\n ENB: BOTH ACTIVE\n"); +#endif + } + else if (TB0_active && TB1_active && tbswap==1) { + dlsch0=dlsch[0]; + dlsch1=dlsch[1]; + dlsch0->active = 1; + dlsch1->active = 1; + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + dlsch0_harq->mcs = mcs1; + dlsch1_harq->mcs = mcs2; + dlsch0_harq->rvidx = rv1; + dlsch1_harq->rvidx = rv2; + dlsch0_harq->status = ACTIVE; + dlsch1_harq->status = ACTIVE; + dlsch0_harq->codeword=1; + dlsch1_harq->codeword=0; + } + else if (TB0_active && (TB1_active==0)) { + dlsch0=dlsch[0]; + dlsch0->active = 1; + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + dlsch0_harq->mcs = mcs1; + dlsch0_harq->rvidx = rv1; + dlsch0_harq->status = ACTIVE; + dlsch0_harq->codeword = 0; + dlsch1=NULL; + dlsch1_harq = NULL; +#ifdef DEBUG_HARQ + printf("\n ENB: TB1 is deactivated, retransmit TB0 transmit in TM6\n"); +#endif + } + else if ((TB0_active==0) && TB1_active) { + dlsch1=dlsch[1]; + dlsch1->active = 1; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + dlsch1_harq->mcs = mcs2; + dlsch1_harq->rvidx = rv2; + dlsch1_harq->status = ACTIVE; + dlsch1_harq->codeword = 0; + dlsch0=NULL; + dlsch0_harq = NULL; +#ifdef DEBUG_HARQ + printf("\n ENB: TB0 is deactivated, retransmit TB1 transmit in TM6\n"); +#endif + } + // printf("[eNB] dlsch0_harq->round = %d, dlsch1_harq->round = %d \n", dlsch0_harq->round, dlsch1_harq->round); + + + if (dlsch0 != NULL){ + dlsch0->subframe_tx[subframe] = 1; + + dlsch0->current_harq_pid = harq_pid; + dlsch0->harq_ids[subframe] = harq_pid; + } + + if (dlsch1_harq != NULL){ + dlsch1->current_harq_pid = harq_pid; + dlsch1->harq_ids[subframe] = harq_pid; + } + + + if (dlsch0 != NULL ){ + conv_rballoc(rah, + rballoc, + frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc); + + dlsch0_harq->nb_rb = conv_nprb(rah, rballoc, frame_parms->N_RB_DL); + + if (dlsch1 != NULL){ + dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0]; + dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; + } + } else if ((dlsch0 == NULL ) && (dlsch1 != NULL )){ + conv_rballoc(rah, + rballoc, + frame_parms->N_RB_DL, + dlsch1_harq->rb_alloc); + + dlsch1_harq->nb_rb = conv_nprb(rah, rballoc, frame_parms->N_RB_DL); + } + + + /*if (dlsch0_harq->nb_rb == 0) + return(-1);*/ + + + // assume both TBs are active + if (dlsch0_harq != NULL) + dlsch0_harq->Nl = 1; + if (dlsch1_harq != NULL) + dlsch1_harq->Nl = 1; + + + // check if either TB is disabled (see 36-213 V11.3 Section ) + + if (frame_parms->nb_antenna_ports_eNB == 2) { + if ((dlsch0 != NULL) && (dlsch1 != NULL)) { //two CW active + + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch1_harq->nb_rb-1]; + switch (tpmi) { + case 0: + dlsch0_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODING1; + dlsch1_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODING1; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,0,1); + dlsch1_harq->pmi_alloc = pmi_extend(frame_parms,0,1); + break; + case 1: + dlsch0_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODINGj; + dlsch1_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODINGj; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1,1); + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1,1); + + break; + case 2: // PUSCH precoding + dlsch0_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING; + dlsch0_harq->pmi_alloc = DL_pmi_single; + dlsch1_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING; + dlsch1_harq->pmi_alloc = DL_pmi_single; + break; + default: + break; + } + } else if ((dlsch0 != NULL) && (dlsch1 == NULL)) { // only CW 0 active + dlsch0_harq->dl_power_off = 1; + dlsch0_harq->TBS= TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + switch (tpmi) { + case 0 : + dlsch0_harq->mimo_mode = ALAMOUTI; + break; + case 1: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING11; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,0,0); + break; + case 2: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1m1; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1,0); + break; + case 3: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1j; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,2,0); + break; + case 4: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1mj; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,3,0); + break; + case 5: + dlsch0_harq->mimo_mode = PUSCH_PRECODING0; + dlsch0_harq->pmi_alloc = DL_pmi_single; + break; + case 6: + dlsch0_harq->mimo_mode = PUSCH_PRECODING1; + dlsch0_harq->pmi_alloc = DL_pmi_single; + break; + } + } else if ((dlsch0 == NULL) && (dlsch1 != NULL)) { + dlsch1_harq->dl_power_off = 1; + dlsch1_harq->TBS= TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch1_harq->nb_rb-1]; + switch (tpmi) { + case 0 : + dlsch1_harq->mimo_mode = ALAMOUTI; + break; + case 1: + dlsch1_harq->mimo_mode = UNIFORM_PRECODING11; + dlsch1_harq->pmi_alloc = pmi_extend(frame_parms,0,0); + break; + case 2: + dlsch1_harq->mimo_mode = UNIFORM_PRECODING1m1; + dlsch1_harq->pmi_alloc = pmi_extend(frame_parms,1,0); + break; + case 3: + dlsch1_harq->mimo_mode = UNIFORM_PRECODING1j; + dlsch1_harq->pmi_alloc = pmi_extend(frame_parms,2,0); + break; + case 4: + dlsch1_harq->mimo_mode = UNIFORM_PRECODING1mj; + dlsch1_harq->pmi_alloc = pmi_extend(frame_parms,3,0); + break; + case 5: + dlsch1_harq->mimo_mode = PUSCH_PRECODING0; + dlsch1_harq->pmi_alloc = DL_pmi_single; + break; + case 6: + dlsch1_harq->mimo_mode = PUSCH_PRECODING1; + dlsch1_harq->pmi_alloc = DL_pmi_single; + break; + } + // printf ("[eNB] dlsch1_harq->pmi_alloc %d\n", dlsch1_harq->pmi_alloc); + } + + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + // fill in later + } + + // reset HARQ process if this is the first transmission + /* if (dlsch0_harq->round == 0) + dlsch0_harq->status = ACTIVE; + + if (dlsch1_harq->round == 0) + dlsch1_harq->status = ACTIVE;*/ + if (dlsch0_harq != NULL) + dlsch0->rnti = rnti; + if (dlsch1 != NULL) + dlsch1->rnti = rnti; + + + break; + + case format2A: + + switch (frame_parms->N_RB_DL) { + + case 6: + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; + } else { + mcs1 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->tpmi; + } + } else { + LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB); + } + + break; + + case 25: + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; + } else { + mcs1 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->tpmi; + } + } else { + LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB); + } + + break; + + case 50: + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->tb_swap; + } else { + mcs1 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->tb_swap; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->tpmi; + } + } else { + LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB); + } + + break; + + case 100: + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->tb_swap; + } else { + mcs1 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->tb_swap; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->tpmi; + } else { + mcs1 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->tpmi; + } + } else { + LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB); + } + + break; + } + + + if (harq_pid>=8) { + LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + + // Flip the TB to codeword mapping as described in 5.3.3.1.5 of 36-212 V11.3.0 + // note that we must set tbswap=0 in eNB scheduler if one TB is deactivated + // This must be set as in TM4, does not work properly now. + if (tbswap == 0) { + dlsch0 = dlsch[0]; + dlsch1 = dlsch[1]; + } else { + dlsch0 = dlsch[1]; + dlsch1 = dlsch[0]; + } + + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + + dlsch0->subframe_tx[subframe] = 1; + + dlsch0->current_harq_pid = harq_pid; + dlsch1->current_harq_pid = harq_pid; + dlsch0->harq_ids[subframe] = harq_pid; + dlsch1->harq_ids[subframe] = harq_pid; + // printf("Setting DLSCH harq id %d to subframe %d\n",harq_pid,subframe); + + + conv_rballoc(rah, + rballoc, + frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc); + + dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0]; + dlsch0_harq->nb_rb = conv_nprb(rah, + rballoc, + frame_parms->N_RB_DL); + dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; + + if (dlsch0_harq->nb_rb == 0) + return(-1); + + dlsch0_harq->mcs = mcs1; + dlsch1_harq->mcs = mcs2; + dlsch0_harq->rvidx = rv1; + dlsch1_harq->rvidx = rv2; + + // assume both TBs are active + dlsch0_harq->Nl = 1; + dlsch1_harq->Nl = 1; + dlsch0->active = 1; + dlsch1->active = 1; + + + // check if either TB is disabled (see 36-213 V11.3 Section ) + if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) { + dlsch0->active = 0; + } + + if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) { + dlsch1->active = 0; + } + + // dlsch0_harq->dl_power_off = 0; + // dlsch1_harq->dl_power_off = 0; + + + if (frame_parms->nb_antenna_ports_eNB == 2) { + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch0_harq->nb_rb-1]; + + if ((dlsch0->active==1) && (dlsch1->active==1)) { + + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + } else { + dlsch0_harq->mimo_mode = ALAMOUTI; + dlsch1_harq->mimo_mode = ALAMOUTI; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { // 4 antenna case + if ((dlsch0->active==1) && (dlsch1->active==1)) { + switch (tpmi) { + case 0: // one layer per transport block + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + break; + + case 1: // one-layers on TB 0, two on TB 1 + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->Nl = 2; + dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][(dlsch1_harq->nb_rb<<1)-1]; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + break; + + case 2: // two-layers on TB 0, two on TB 1 + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch0_harq->Nl = 2; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + + if (frame_parms->N_RB_DL <= 56) { + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][(dlsch0_harq->nb_rb<<1)-1]; + dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][(dlsch1_harq->nb_rb<<1)-1]; + } else { + LOG_E(PHY,"Add implementation of Table 7.1.7.2.2-1 for two-layer TBS conversion with N_RB_DL > 56\n"); + } + + break; + + case 3: // + LOG_E(PHY,"Illegal value (3) for TPMI in Format 2A DCI\n"); + break; + } + } else if (dlsch0->active == 1) { + switch (tpmi) { + case 0: // one layer per transport block + dlsch0_harq->mimo_mode = ALAMOUTI; + dlsch1_harq->mimo_mode = ALAMOUTI; + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + break; + + case 1: // two-layers on TB 0 + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch0_harq->Nl = 2; + dlsch0_harq->dl_power_off = 1; + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][(dlsch0_harq->nb_rb<<1)-1]; + break; + + case 2: // two-layers on TB 0, two on TB 1 + case 3: // + LOG_E(PHY,"Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n",tpmi); + break; + } + } else if (dlsch1->active == 1) { + switch (tpmi) { + case 0: // one layer per transport block + dlsch0_harq->mimo_mode = ALAMOUTI; + dlsch1_harq->mimo_mode = ALAMOUTI; + dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch1_harq->nb_rb-1]; + break; + + case 1: // two-layers on TB 0 + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->Nl = 2; + dlsch1_harq->dl_power_off = 1; + dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][(dlsch1_harq->nb_rb<<1)-1]; + break; + + case 2: // two-layers on TB 0, two on TB 1 + case 3: // + LOG_E(PHY,"Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n",tpmi); + break; + } + } + } else { + LOG_E(PHY,"Illegal number of antennas for eNB %d\n",frame_parms->nb_antenna_ports_eNB); + } + + // reset HARQ process if this is the first transmission + if ((dlsch0->active==1) && (dlsch0_harq->round == 0)) + dlsch0_harq->status = ACTIVE; + + if ((dlsch1->active==1) && (dlsch1_harq->round == 0)) + dlsch1_harq->status = ACTIVE; + + dlsch0->rnti = rnti; + dlsch1->rnti = rnti; + + + // printf("eNB: Format 2A TBS0 %d, TBS1 %d\n",dlsch0_harq->TBS,dlsch1_harq->TBS); + + break; + + case format2B: + + switch (frame_parms->N_RB_DL) { + + case 6: + if (frame_type == TDD) { + mcs1 = ((DCI2B_1_5MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2B_1_5MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2B_1_5MHz_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2B_1_5MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2B_1_5MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2B_1_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2B_1_5MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2B_1_5MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2B_1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2B_1_5MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2B_1_5MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2B_1_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 25: + if (frame_type == TDD) { + mcs1 = ((DCI2B_5MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2B_5MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2B_5MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2B_5MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2B_5MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2B_5MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2B_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2B_5MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2B_5MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2B_5MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2B_5MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2B_5MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2B_5MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2B_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 50: + if (frame_type == TDD) { + mcs1 = ((DCI2B_10MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2B_10MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2B_10MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2B_10MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2B_10MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2B_10MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2B_10MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2B_10MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2B_10MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2B_10MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2B_10MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2B_10MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2B_10MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2B_10MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 100: + if (frame_type == TDD) { + mcs1 = ((DCI2B_20MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2B_20MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2B_20MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2B_20MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2B_20MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2B_20MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2B_20MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2B_20MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2B_20MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2B_20MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2B_20MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2B_20MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2B_20MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2B_20MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + } + + + if (harq_pid>=8) { + LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + + + dlsch0 = dlsch[0]; + dlsch1 = dlsch[1]; + + + dlsch0->subframe_tx[subframe] = 1; + + dlsch0->current_harq_pid = harq_pid; + dlsch1->current_harq_pid = harq_pid; + dlsch0->harq_ids[subframe] = harq_pid; + dlsch1->harq_ids[subframe] = harq_pid; + // printf("Setting DLSCH harq id %d to subframe %d\n",harq_pid,subframe); + + + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + + // Needs to be checked + dlsch0_harq->codeword=0; + dlsch1_harq->codeword=1; + + conv_rballoc(rah, + rballoc, + frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc); + + dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0]; + + dlsch0_harq->nb_rb = conv_nprb(rah, + rballoc, + frame_parms->N_RB_DL); + dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; + + dlsch0_harq->mcs = mcs1; + dlsch1_harq->mcs = mcs2; + dlsch0_harq->rvidx = rv1; + dlsch1_harq->rvidx = rv2; + + // check if either TB is disabled (see 36-213 V8.6 p. 26) + + + if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) + dlsch0_harq->status = DISABLED; + + if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) + dlsch1_harq->status = DISABLED; + + dlsch0_harq->Nl = 1; + + + if (dlsch0_harq->round == 0) { + dlsch0_harq->status = ACTIVE; + // printf("Setting DLSCH process %d to ACTIVE\n",harq_pid); + } + + dlsch0_harq->mcs = mcs1; + + if (dlsch0_harq->nb_rb > 0) { + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + } else { + dlsch0_harq->TBS = 0; + } + + dlsch0->active = 1; + + dlsch0->rnti = rnti; + dlsch1->rnti = rnti; + + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + + break; + + case format2C: + + switch (frame_parms->N_RB_DL) { + + case 6: + if (frame_type == TDD) { + mcs1 = ((DCI2C_1_5MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2C_1_5MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2C_1_5MHz_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2C_1_5MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2C_1_5MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2C_1_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2C_1_5MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2C_1_5MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2C_1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2C_1_5MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2C_1_5MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2C_1_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 25: + if (frame_type == TDD) { + mcs1 = ((DCI2C_5MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2C_5MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2C_5MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2C_5MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2C_5MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2C_5MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2C_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2C_5MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2C_5MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2C_5MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2C_5MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2C_5MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2C_5MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2C_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 50: + if (frame_type == TDD) { + mcs1 = ((DCI2C_10MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2C_10MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2C_10MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2C_10MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2C_10MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2C_10MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2C_10MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2C_10MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2C_10MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2C_10MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2C_10MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2C_10MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2C_10MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2C_10MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 100: + if (frame_type == TDD) { + mcs1 = ((DCI2C_20MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2C_20MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2C_20MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2C_20MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2C_20MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2C_20MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2C_20MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2C_20MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2C_20MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2C_20MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2C_20MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2C_20MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2C_20MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2C_20MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + } + + + if (harq_pid>=8) { + LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + + + dlsch0 = dlsch[0]; + dlsch1 = dlsch[1]; + + dlsch0->subframe_tx[subframe] = 1; + + dlsch0->current_harq_pid = harq_pid; + dlsch1->current_harq_pid = harq_pid; + dlsch0->harq_ids[subframe] = harq_pid; + dlsch1->harq_ids[subframe] = harq_pid; + // printf("Setting DLSCH harq id %d to subframe %d\n",harq_pid,subframe); + + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + + // Needs to be checked + dlsch0_harq->codeword=0; + dlsch1_harq->codeword=1; + + conv_rballoc(rah, + rballoc, + frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc); + dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0]; + + dlsch0_harq->nb_rb = conv_nprb(rah, + rballoc, + frame_parms->N_RB_DL); + dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; + + if (dlsch0_harq->nb_rb == 0) + return(-1); + + dlsch0_harq->mcs = mcs1; + dlsch1_harq->mcs = mcs2; + dlsch0_harq->rvidx = rv1; + dlsch1_harq->rvidx = rv2; + + // check if either TB is disabled (see 36-213 V8.6 p. 26) + + + if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) { + dlsch0->active = 0; + } + + if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) { + dlsch1->active = 0; + } + + + + if ((dlsch0_harq->round == 0) && (dlsch0->active == 1) ) { + dlsch0_harq->status = ACTIVE; + dlsch0_harq->mcs = mcs1; + } + + if ((dlsch1_harq->round == 0) && (dlsch1->active == 1) ) { + dlsch1_harq->status = ACTIVE; + dlsch1_harq->mcs = mcs2; + } + + // check TPMI information to compute TBS + if (frame_parms->nb_antenna_ports_eNB == 2) { + if (dlsch1->active == 1) { // both TBs are active + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch0_harq->nb_rb-1]; + } else { + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + + } + + dlsch0->rnti = rnti; + dlsch1->rnti = rnti; + + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + + break; + + case format2D: + + switch (frame_parms->N_RB_DL) { + + case 6: + if (frame_type == TDD) { + mcs1 = ((DCI2D_1_5MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2D_1_5MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2D_1_5MHz_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2D_1_5MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2D_1_5MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2D_1_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2D_1_5MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2D_1_5MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2D_1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2D_1_5MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2D_1_5MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2D_1_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 25: + if (frame_type == TDD) { + mcs1 = ((DCI2D_5MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2D_5MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2D_5MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2D_5MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2D_5MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2D_5MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2D_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2D_5MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2D_5MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2D_5MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2D_5MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2D_5MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2D_5MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2D_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 50: + if (frame_type == TDD) { + mcs1 = ((DCI2D_10MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2D_10MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2D_10MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2D_10MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2D_10MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2D_10MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2D_10MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2D_10MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2D_10MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2D_10MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2D_10MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2D_10MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2D_10MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2D_10MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 100: + if (frame_type == TDD) { + mcs1 = ((DCI2D_20MHz_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2D_20MHz_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2D_20MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2D_20MHz_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2D_20MHz_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2D_20MHz_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2D_20MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs1 = ((DCI2D_20MHz_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2D_20MHz_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2D_20MHz_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2D_20MHz_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2D_20MHz_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2D_20MHz_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2D_20MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + } + + + if (harq_pid>=8) { + LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + + + dlsch0 = dlsch[0]; + dlsch1 = dlsch[1]; + + dlsch0->subframe_tx[subframe] = 1; + + dlsch0->current_harq_pid = harq_pid; + dlsch1->current_harq_pid = harq_pid; + dlsch0->harq_ids[subframe] = harq_pid; + dlsch1->harq_ids[subframe] = harq_pid; + // printf("Setting DLSCH harq id %d to subframe %d\n",harq_pid,subframe); + + + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + + // Needs to be checked + dlsch0_harq->codeword=0; + dlsch1_harq->codeword=1; + + conv_rballoc(rah, + rballoc, + frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc); + dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0]; + + dlsch0_harq->nb_rb = conv_nprb(rah, + rballoc, + frame_parms->N_RB_DL); + dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; + + dlsch0_harq->mcs = mcs1; + dlsch1_harq->mcs = mcs2; + dlsch0_harq->rvidx = rv1; + dlsch1_harq->rvidx = rv2; + + // check if either TB is disabled (see 36-213 V8.6 p. 26) + + + if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) + dlsch0_harq->status = DISABLED; + + if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) + dlsch1_harq->status = DISABLED; + + dlsch0_harq->Nl = 1; + + + if (dlsch0_harq->round == 0) { + dlsch0_harq->status = ACTIVE; + // printf("Setting DLSCH process %d to ACTIVE\n",harq_pid); + } + + dlsch0_harq->mcs = mcs1; + + if (dlsch0_harq->nb_rb > 0) { + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + } else { + dlsch0_harq->TBS = 0; + } + + dlsch0->active = 1; + + dlsch0->rnti = rnti; + dlsch1->rnti = rnti; + + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + + break; + + + case format1E_2A_M10PRB: + + harq_pid = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->harq_pid; + + if (harq_pid>=8) { + LOG_E(PHY,"ERROR: Format 1E_2A_M10PRB: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + /* + tbswap = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tb_swap; + if (tbswap == 0) { + dlsch0 = dlsch[0]; + dlsch1 = dlsch[1]; + } + else{ + dlsch0 = dlsch[1]; + dlsch1 = dlsch[0]; + } + */ + dlsch0 = dlsch[0]; + dlsch0->subframe_tx[subframe] = 1; + + dlsch0->current_harq_pid = harq_pid; + //dlsch1->current_harq_pid = harq_pid; + dlsch0->harq_ids[subframe] = harq_pid; + //dlsch1->harq_ids[subframe] = harq_pid; + // printf("Setting DLSCH harq id %d to subframe %d\n",harq_pid,subframe); + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + // Needs to be checked + dlsch0_harq->codeword=0; + + conv_rballoc(((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rah, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rballoc,frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc); + + //dlsch1->rb_alloc[0] = dlsch0->rb_alloc[0]; + + dlsch0_harq->nb_rb = conv_nprb(((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rah, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rballoc, + frame_parms->N_RB_DL); + //dlsch1->nb_rb = dlsch0->nb_rb; + + dlsch0_harq->mcs = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->mcs; + //dlsch1_harq->mcs = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->mcs2; + dlsch0_harq->rvidx = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rv; + //dlsch1_harq->rvidx = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rv2; + + // check if either TB is disabled (see 36-213 V8.6 p. 26) --> only for format 2 and 2A + + //if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) + // dlsch0_harq->status = DISABLED; + + //if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) + // dlsch1_harq->status = DISABLED; + + dlsch0_harq->Nl = 1; + + //dlsch0->layer_index = tbswap; + //dlsch1->layer_index = 1-tbswap; + + // Fix this + tpmi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tpmi; + + switch (tpmi) { + case 0 : + dlsch0_harq->mimo_mode = ALAMOUTI; + break; + + case 1: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING11; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,0, 0); + + break; + + case 2: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1m1; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1, 0); + + break; + + case 3: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1j; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,2, 0); + + break; + + case 4: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1mj; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,3, 0); + break; + + case 5: + dlsch0_harq->mimo_mode = PUSCH_PRECODING0; + dlsch0_harq->pmi_alloc = DL_pmi_single; + break; + + case 6: + dlsch0_harq->mimo_mode = PUSCH_PRECODING1; + return(-1); + break; + } + + // printf("Set pmi %x (tpmi %d)\n",dlsch0->pmi_alloc,tpmi); + + + if (frame_parms->mode1_flag == 1) + dlsch0_harq->mimo_mode = SISO; + + // dlsch0_harq->Ndi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi; + if (dlsch0_harq->round == 0) { + dlsch0_harq->status = ACTIVE; + // printf("Setting DLSCH process %d to ACTIVE\n",harq_pid); + } + + dlsch0_harq->mcs = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->mcs; + + if (dlsch0_harq->nb_rb > 0) { + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + } else { + dlsch0_harq->TBS = 0; + } + + dlsch0->active = 1; + + dlsch0->rnti = rnti; + //dlsch1->rnti = rnti; + + // dlsch0->dl_power_off = 1; + dlsch0_harq->dl_power_off = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->dl_power_off; + //dlsch1->dl_power_off = 1; + + break; + + default: + LOG_E(PHY,"Unknown DCI format\n"); + return(-1); + break; + } + + + if (dlsch0_harq) { + dlsch0_harq->frame = frame; + dlsch0_harq->subframe = subframe; + } + if (dlsch1_harq) { + dlsch1_harq->frame = frame; + dlsch1_harq->subframe = subframe; + } + +#ifdef DEBUG_DCI + + if (dlsch0) { + printf("dlsch0 eNB: dlsch0 %p\n",dlsch0); + printf("dlsch0 eNB: rnti %x\n",dlsch0->rnti); + printf("dlsch0 eNB: NBRB %d\n",dlsch0_harq->nb_rb); + printf("dlsch0 eNB: rballoc %x\n",dlsch0_harq->rb_alloc[0]); + printf("dlsch0 eNB: harq_pid %d\n",harq_pid); + printf("dlsch0 eNB: round %d\n",dlsch0_harq->round); + printf("dlsch0 eNB: rvidx %d\n",dlsch0_harq->rvidx); + printf("dlsch0 eNB: TBS %d (NPRB %d)\n",dlsch0_harq->TBS,NPRB); + printf("dlsch0 eNB: mcs %d\n",dlsch0_harq->mcs); + printf("dlsch0 eNB: tpmi %d\n",tpmi); + printf("dlsch0 eNB: mimo_mode %d\n",dlsch0_harq->mimo_mode); + } + + if (dlsch1) { + printf("dlsch1 eNB: dlsch1 %p\n",dlsch1); + printf("dlsch1 eNB: rnti %x\n",dlsch1->rnti); + printf("dlsch1 eNB: NBRB %d\n",dlsch1_harq->nb_rb); + printf("dlsch1 eNB: rballoc %x\n",dlsch1_harq->rb_alloc[0]); + printf("dlsch1 eNB: harq_pid %d\n",harq_pid); + printf("dlsch1 eNB: round %d\n",dlsch1_harq->round); + printf("dlsch1 eNB: rvidx %d\n",dlsch1_harq->rvidx); + printf("dlsch1 eNB: TBS %d (NPRB %d)\n",dlsch1_harq->TBS,NPRB); + printf("dlsch1 eNB: mcs %d\n",dlsch1_harq->mcs); + printf("dlsch1 eNB: tpmi %d\n",tpmi); + printf("dlsch1 eNB: mimo_mode %d\n",dlsch1_harq->mimo_mode); + } + +#endif + + // compute DL power control parameters + + if (dlsch0 != NULL){ + computeRhoA_eNB(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off, frame_parms->nb_antenna_ports_eNB); + computeRhoB_eNB(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[0],dlsch0_harq->dl_power_off); +} + if (dlsch1 != NULL){ + computeRhoA_eNB(pdsch_config_dedicated, dlsch[1],dlsch1_harq->dl_power_off, frame_parms->nb_antenna_ports_eNB); + computeRhoB_eNB(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[1],dlsch1_harq->dl_power_off); + } + + + return(0); +} + + +int dump_dci(NR_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci) +{ + switch (dci->format) { + + case format0: // This is an UL SCH allocation so nothing here, inform MAC + if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config>0)) + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format0 (TDD, 1.5MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, dai %d, cqi_req %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu[0])[0], + ((DCI0_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->hopping, + ((DCI0_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc, + ((DCI0_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->mcs, + ((DCI0_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->ndi, + ((DCI0_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->TPC, + ((DCI0_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->cshift, + ((DCI0_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->dai, + ((DCI0_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->cqi_req); + break; + + case 25: + LOG_D(PHY,"DCI format0 (TDD1-6, 5MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, dai %d, cqi_req %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu[0])[0], + ((DCI0_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->hopping, + ((DCI0_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc, + ((DCI0_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->mcs, + ((DCI0_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->ndi, + ((DCI0_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->TPC, + ((DCI0_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->cshift, + ((DCI0_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->dai, + ((DCI0_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->cqi_req); + break; + + case 50: + LOG_D(PHY,"DCI format0 (TDD1-6, 10MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, dai %d, cqi_req %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu[0])[0], + ((DCI0_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->hopping, + ((DCI0_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc, + ((DCI0_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->mcs, + ((DCI0_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->ndi, + ((DCI0_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->TPC, + ((DCI0_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->cshift, + ((DCI0_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->dai, + ((DCI0_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->cqi_req); + break; + + case 100: + LOG_D(PHY,"DCI format0 (TDD1-6, 20MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, dai %d, cqi_req %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu[0])[0], + ((DCI0_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->hopping, + ((DCI0_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc, + ((DCI0_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->mcs, + ((DCI0_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->ndi, + ((DCI0_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->TPC, + ((DCI0_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->cshift, + ((DCI0_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->dai, + ((DCI0_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->cqi_req); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + else if (frame_parms->frame_type == FDD) + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format0 (FDD, 1.5MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, cqi_req %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu[0])[0], + ((DCI0_1_5MHz_FDD_t *)&dci->dci_pdu[0])->hopping, + ((DCI0_1_5MHz_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI0_1_5MHz_FDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI0_1_5MHz_FDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI0_1_5MHz_FDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI0_1_5MHz_FDD_t *)&dci->dci_pdu[0])->cshift, + ((DCI0_1_5MHz_FDD_t *)&dci->dci_pdu[0])->cqi_req); + break; + + case 25: + LOG_D(PHY,"DCI format0 (FDD, 5MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, cqi_req %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu[0])[0], + ((DCI0_5MHz_FDD_t *)&dci->dci_pdu[0])->hopping, + ((DCI0_5MHz_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI0_5MHz_FDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI0_5MHz_FDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI0_5MHz_FDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI0_5MHz_FDD_t *)&dci->dci_pdu[0])->cshift, + ((DCI0_5MHz_FDD_t *)&dci->dci_pdu[0])->cqi_req); + break; + + case 50: + LOG_D(PHY,"DCI format0 (FDD, 10MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, cqi_req %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu[0])[0], + ((DCI0_10MHz_FDD_t *)&dci->dci_pdu[0])->hopping, + ((DCI0_10MHz_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI0_10MHz_FDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI0_10MHz_FDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI0_10MHz_FDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI0_10MHz_FDD_t *)&dci->dci_pdu[0])->cshift, + ((DCI0_10MHz_FDD_t *)&dci->dci_pdu[0])->cqi_req); + break; + + case 100: + LOG_D(PHY,"DCI format0 (FDD, 20MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, cqi_req %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu[0])[0], + ((DCI0_20MHz_FDD_t *)&dci->dci_pdu[0])->hopping, + ((DCI0_20MHz_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI0_20MHz_FDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI0_20MHz_FDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI0_20MHz_FDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI0_20MHz_FDD_t *)&dci->dci_pdu[0])->cshift, + ((DCI0_20MHz_FDD_t *)&dci->dci_pdu[0])->cqi_req); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + else + LOG_E(PHY,"Don't know how to handle TDD format 0 yet\n"); + + break; + + case format1: + if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config>0)) + + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format1 (TDD 1.5 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d, harq_pid %d, ndi %d, RV %d, TPC %d, dai %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI1_1_5MHz_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1_1_5MHz_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1_1_5MHz_TDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1_1_5MHz_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI1_1_5MHz_TDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1_1_5MHz_TDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1_1_5MHz_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI1_1_5MHz_TDD_t *)&dci->dci_pdu[0])->dai); + break; + + case 25: + LOG_D(PHY,"DCI format1 (TDD 5 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d, harq_pid %d, ndi %d, RV %d, TPC %d, dai %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI1_5MHz_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1_5MHz_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1_5MHz_TDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1_5MHz_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI1_5MHz_TDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1_5MHz_TDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1_5MHz_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI1_5MHz_TDD_t *)&dci->dci_pdu[0])->dai); + break; + + case 50: + LOG_D(PHY,"DCI format1 (TDD 10 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d, harq_pid %d, ndi %d, RV %d, TPC %d, dai %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI1_10MHz_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1_10MHz_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1_10MHz_TDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1_10MHz_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI1_10MHz_TDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1_10MHz_TDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1_10MHz_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI1_10MHz_TDD_t *)&dci->dci_pdu[0])->dai); + break; + + case 100: + LOG_D(PHY,"DCI format1 (TDD 20 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d, harq_pid %d, ndi %d, RV %d, TPC %d, dai %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI1_20MHz_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1_20MHz_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1_20MHz_TDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1_20MHz_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI1_20MHz_TDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1_20MHz_TDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1_20MHz_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI1_20MHz_TDD_t *)&dci->dci_pdu[0])->dai); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + else if (frame_parms->frame_type == FDD) { + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format1 (FDD, 1.5 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d, harq_pid %d, ndi %d, RV %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI1_1_5MHz_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1_1_5MHz_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1_1_5MHz_FDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1_1_5MHz_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI1_1_5MHz_FDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1_1_5MHz_FDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1_1_5MHz_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 25: + LOG_D(PHY,"DCI format1 (FDD, 5 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d, harq_pid %d, ndi %d, RV %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI1_5MHz_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1_5MHz_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1_5MHz_FDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1_5MHz_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI1_5MHz_FDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1_5MHz_FDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1_5MHz_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 50: + LOG_D(PHY,"DCI format1 (FDD, 10 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d, harq_pid %d, ndi %d, RV %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI1_10MHz_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1_10MHz_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1_10MHz_FDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1_10MHz_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI1_10MHz_FDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1_10MHz_FDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1_10MHz_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 100: + LOG_D(PHY,"DCI format1 (FDD, 20 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d, harq_pid %d, ndi %d, RV %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI1_20MHz_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1_20MHz_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1_20MHz_FDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1_20MHz_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI1_20MHz_FDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1_20MHz_FDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1_20MHz_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } + + else + LOG_E(PHY,"Don't know how to handle TDD format 0 yet\n"); + + break; + + case format1A: // This is DLSCH allocation for control traffic + if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config>0)) { + switch (frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format1A (TDD1-6, 1_5MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"VRB_TYPE %d\n",((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->vrb_type); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT25[((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc]); + LOG_D(PHY,"MCS %d\n",((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->mcs); + LOG_D(PHY,"HARQ_PID %d\n",((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->harq_pid); + LOG_D(PHY,"NDI %d\n",((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->ndi); + LOG_D(PHY,"RV %d\n",((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rv); + LOG_D(PHY,"TPC %d\n",((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->TPC); + LOG_D(PHY,"DAI %d\n",((DCI1A_1_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->dai); + break; + + case 25: + LOG_D(PHY,"DCI format1A (TDD1-6, 5MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"VRB_TYPE %d\n",((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->vrb_type); + LOG_D(PHY,"RB_ALLOC %d (NB_RB %d)\n",((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT25[((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc]); + LOG_D(PHY,"MCS %d\n",((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->mcs); + LOG_D(PHY,"HARQ_PID %d\n",((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->harq_pid); + LOG_D(PHY,"NDI %d\n",((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->ndi); + LOG_D(PHY,"RV %d\n",((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rv); + LOG_D(PHY,"TPC %d\n",((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->TPC); + LOG_D(PHY,"DAI %d\n",((DCI1A_5MHz_TDD_1_6_t *)&dci->dci_pdu[0])->dai); + break; + + case 50: + LOG_D(PHY,"DCI format1A (TDD1-6, 10MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"VRB_TYPE %d\n",((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->vrb_type); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT50[((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc]); + LOG_D(PHY,"MCS %d\n",((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->mcs); + LOG_D(PHY,"HARQ_PID %d\n",((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->harq_pid); + LOG_D(PHY,"NDI %d\n",((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->ndi); + LOG_D(PHY,"RV %d\n",((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rv); + LOG_D(PHY,"TPC %d\n",((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->TPC); + LOG_D(PHY,"DAI %d\n",((DCI1A_10MHz_TDD_1_6_t *)&dci->dci_pdu[0])->dai); + break; + + case 100: + LOG_D(PHY,"DCI format1A (TDD1-6, 20MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"VRB_TYPE %d\n",((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->vrb_type); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT100[((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rballoc]); + LOG_D(PHY,"MCS %d\n",((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->mcs); + LOG_D(PHY,"HARQ_PID %d\n",((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->harq_pid); + LOG_D(PHY,"NDI %d\n",((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->ndi); + LOG_D(PHY,"RV %d\n",((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->rv); + LOG_D(PHY,"TPC %d\n",((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->TPC); + LOG_D(PHY,"DAI %d\n",((DCI1A_20MHz_TDD_1_6_t *)&dci->dci_pdu[0])->dai); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + + } else if (frame_parms->frame_type == FDD) { + switch (frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format1A(FDD, 1.5MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"VRB_TYPE %d\n",((DCI1A_1_5MHz_FDD_t *)&dci->dci_pdu[0])->vrb_type); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1A_1_5MHz_FDD_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT25[((DCI1A_1_5MHz_FDD_t *)&dci->dci_pdu[0])->rballoc]); + LOG_D(PHY,"MCS %d\n",((DCI1A_1_5MHz_FDD_t *)&dci->dci_pdu[0])->mcs); + LOG_D(PHY,"HARQ_PID %d\n",((DCI1A_1_5MHz_FDD_t *)&dci->dci_pdu[0])->harq_pid); + LOG_D(PHY,"NDI %d\n",((DCI1A_1_5MHz_FDD_t *)&dci->dci_pdu[0])->ndi); + LOG_D(PHY,"RV %d\n",((DCI1A_1_5MHz_FDD_t *)&dci->dci_pdu[0])->rv); + LOG_D(PHY,"TPC %d\n",((DCI1A_1_5MHz_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 25: + LOG_D(PHY,"DCI format1A(FDD, 5MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"VRB_TYPE %d\n",((DCI1A_5MHz_FDD_t *)&dci->dci_pdu[0])->vrb_type); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1A_5MHz_FDD_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT25[((DCI1A_5MHz_FDD_t *)&dci->dci_pdu[0])->rballoc]); + LOG_D(PHY,"MCS %d\n",((DCI1A_5MHz_FDD_t *)&dci->dci_pdu[0])->mcs); + LOG_D(PHY,"HARQ_PID %d\n",((DCI1A_5MHz_FDD_t *)&dci->dci_pdu[0])->harq_pid); + LOG_D(PHY,"NDI %d\n",((DCI1A_5MHz_FDD_t *)&dci->dci_pdu[0])->ndi); + LOG_D(PHY,"RV %d\n",((DCI1A_5MHz_FDD_t *)&dci->dci_pdu[0])->rv); + LOG_D(PHY,"TPC %d\n",((DCI1A_5MHz_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 50: + LOG_D(PHY,"DCI format1A(FDD, 10MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"VRB_TYPE %d\n",((DCI1A_10MHz_FDD_t *)&dci->dci_pdu[0])->vrb_type); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1A_10MHz_FDD_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT50[((DCI1A_10MHz_FDD_t *)&dci->dci_pdu[0])->rballoc]); + LOG_D(PHY,"MCS %d\n",((DCI1A_10MHz_FDD_t *)&dci->dci_pdu[0])->mcs); + LOG_D(PHY,"HARQ_PID %d\n",((DCI1A_10MHz_FDD_t *)&dci->dci_pdu[0])->harq_pid); + LOG_D(PHY,"NDI %d\n",((DCI1A_10MHz_FDD_t *)&dci->dci_pdu[0])->ndi); + LOG_D(PHY,"RV %d\n",((DCI1A_10MHz_FDD_t *)&dci->dci_pdu[0])->rv); + LOG_D(PHY,"TPC %d\n",((DCI1A_10MHz_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 100: + LOG_D(PHY,"DCI format1A(FDD, 20MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"VRB_TYPE %d\n",((DCI1A_20MHz_FDD_t *)&dci->dci_pdu[0])->vrb_type); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1A_20MHz_FDD_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT100[((DCI1A_20MHz_FDD_t *)&dci->dci_pdu[0])->rballoc]); + LOG_D(PHY,"MCS %d\n",((DCI1A_20MHz_FDD_t *)&dci->dci_pdu[0])->mcs); + LOG_D(PHY,"HARQ_PID %d\n",((DCI1A_20MHz_FDD_t *)&dci->dci_pdu[0])->harq_pid); + LOG_D(PHY,"NDI %d\n",((DCI1A_20MHz_FDD_t *)&dci->dci_pdu[0])->ndi); + LOG_D(PHY,"RV %d\n",((DCI1A_20MHz_FDD_t *)&dci->dci_pdu[0])->rv); + LOG_D(PHY,"TPC %d\n",((DCI1A_20MHz_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } + + break; + + case format1C: // This is DLSCH allocation for control traffic + switch (frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format1C (1.5MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n", + ((DCI1C_1_5MHz_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT6[conv_1C_RIV(((DCI1C_1_5MHz_t *)&dci->dci_pdu[0])->rballoc,6)]); + LOG_D(PHY,"MCS %d\n",((DCI1C_1_5MHz_t *)&dci->dci_pdu[0])->mcs); + break; + + case 25: + LOG_D(PHY,"DCI format1C (5MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1C_5MHz_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT25[conv_1C_RIV(((DCI1C_5MHz_t *)&dci->dci_pdu[0])->rballoc,25)]); + LOG_D(PHY,"MCS %d\n",((DCI1C_5MHz_t *)&dci->dci_pdu[0])->mcs); + break; + + case 50: + LOG_D(PHY,"DCI format1C (10MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"Ngap %d\n",((DCI1C_10MHz_t *)&dci->dci_pdu[0])->Ngap); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1C_10MHz_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT50[conv_1C_RIV(((DCI1C_10MHz_t *)&dci->dci_pdu[0])->rballoc,50)]); + LOG_D(PHY,"MCS %d\n",((DCI1C_10MHz_t *)&dci->dci_pdu[0])->mcs); + break; + + case 100: + LOG_D(PHY,"DCI format1C (20MHz), rnti %x (%x)\n",dci->rnti,((uint32_t*)&dci->dci_pdu[0])[0]); + LOG_D(PHY,"Ngap %d\n",((DCI1C_20MHz_t *)&dci->dci_pdu[0])->Ngap); + LOG_D(PHY,"RB_ALLOC %x (NB_RB %d)\n",((DCI1C_20MHz_t *)&dci->dci_pdu[0])->rballoc,RIV2nb_rb_LUT50[conv_1C_RIV(((DCI1C_20MHz_t *)&dci->dci_pdu[0])->rballoc,100)]); + LOG_D(PHY,"MCS %d\n",((DCI1C_20MHz_t *)&dci->dci_pdu[0])->mcs); + break; + + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + + + break; + + case format2: + + if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config>0)) { + if (frame_parms->nb_antenna_ports_eNB == 2) { + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format2 2 antennas (TDD 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, TPC %d, dai %d, tbswap %d, tpmi %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->tpmi + ); + break; + + case 25: + LOG_D(PHY,"DCI format2 2 antennas (TDD 5 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, TPC %d, dai %d, tb_swap %d, tpmi %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + case 50: + LOG_D(PHY,"DCI format2 2 antennas (TDD 10 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, TPC %d, dai %d, tb_swap %d, tpmi %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + case 100: + LOG_D(PHY,"DCI format2 2 antennas (TDD 20 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, TPC %d, dai %d, tb_swap %d, tpmi %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format2 2 antennas (TDD 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, TPC %d, dai %d, tbswap %d, tpmi %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->tpmi + ); + break; + + case 25: + LOG_D(PHY,"DCI format2 2 antennas (TDD 5 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, TPC %d, dai %d, tb_swap %d, tpmi %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + case 50: + LOG_D(PHY,"DCI format2 2 antennas (TDD 10 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, TPC %d, dai %d, tb_swap %d, tpmi %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + case 100: + LOG_D(PHY,"DCI format2 2 antennas (TDD 20 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, TPC %d, dai %d, tb_swap %d, tpmi %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } + } else if (frame_parms->frame_type == FDD) { + if (frame_parms->nb_antenna_ports_eNB == 2) { + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format2 2 antennas (FDD, 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 25: + + LOG_D(PHY,"DCI format2 2 antennas (FDD, 5 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, swap %d, TPMI %d, TPC %d\n", + + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 50: + LOG_D(PHY,"DCI format2 2 antennas (FDD, 10 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 100: + LOG_D(PHY,"DCI format2 2 antennas (FDD, 20 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + switch(frame_parms->N_RB_DL) { + + case 6: + LOG_D(PHY,"DCI format2 4 antennas (FDD, 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 25: + LOG_D(PHY,"DCI format2 4 antennas (FDD, 5 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 50: + LOG_D(PHY,"DCI format2 4 antennas (FDD, 10 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 100: + LOG_D(PHY,"DCI format2 4 antennas (FDD, 20 MHz), rnti %x (%x): rah %d, rb_alloc %x, mcs %d|%d, harq_pid %d, ndi %d|%d, RV %d|%d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } + } + + else + LOG_E(PHY,"Don't know how to handle TDD format 0 yet\n"); + + break; + + case format2A: + + if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config>0)) { + if (frame_parms->nb_antenna_ports_eNB == 2) { + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format2A 2 antennas (FDD 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2A_1_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->tb_swap + ); + break; + + case 25: + LOG_D(PHY,"DCI format2A 2 antennas (FDD 5 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2A_5MHz_2A_TDD_t *)&dci->dci_pdu[0])->tb_swap); + break; + + case 50: + LOG_D(PHY,"DCI format2A 2 antennas (FDD 10 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2A_10MHz_2A_TDD_t *)&dci->dci_pdu[0])->tb_swap); + break; + + case 100: + LOG_D(PHY,"DCI format2A 2 antennas (FDD 20 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2A_20MHz_2A_TDD_t *)&dci->dci_pdu[0])->tb_swap); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format2A 4 antennas (TDD 1.5 MHz), rnti %x (%"PRIu64"): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d, tpmi %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_1_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->tpmi + ); + break; + + case 25: + LOG_D(PHY,"DCI format2A 4 antennas (TDD 5 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d, tpmi %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_5MHz_4A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + case 50: + LOG_D(PHY,"DCI format2A 4 antennas (TDD 10 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d, tpmi %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_10MHz_4A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + case 100: + LOG_D(PHY,"DCI format2A 4 antennas (TDD 20 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d, tpmi %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->TPC, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->dai, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_20MHz_4A_TDD_t *)&dci->dci_pdu[0])->tpmi); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } + } else if (frame_parms->frame_type == FDD) { + if (frame_parms->nb_antenna_ports_eNB == 2) { + switch(frame_parms->N_RB_DL) { + case 6: + LOG_D(PHY,"DCI format2A 2 antennas (FDD, 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, TPC %d\n", + dci->rnti, + ((uint32_t*)&dci->dci_pdu)[0], + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_1_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 25: + LOG_D(PHY,"DCI format2A 2 antennas (FDD, 5 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, TPC %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_5MHz_2A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 50: + LOG_D(PHY,"DCI format2A 2 antennas (FDD, 10 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, TPC %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_10MHz_2A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 100: + LOG_D(PHY,"DCI format2A 2 antennas (FDD, 20 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, TPC %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_20MHz_2A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } else if (frame_parms->nb_antenna_ports_eNB == 4) { + switch(frame_parms->N_RB_DL) { + + case 6: + LOG_D(PHY,"DCI format2A 4 antennas (FDD, 1.5 MHz), rnti %x (%"PRIu64"): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2A_1_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 25: + LOG_D(PHY,"DCI format2A 4 antennas (FDD, 5 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2A_5MHz_4A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 50: + LOG_D(PHY,"DCI format2A 4 antennas (FDD, 5 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2A_10MHz_4A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + case 100: + LOG_D(PHY,"DCI format2A 4 antennas (FDD, 5 MHz), rnti %x (%"PRIu64"): rah %d, rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, tpmi %d, TPC %d\n", + dci->rnti, + ((uint64_t*)&dci->dci_pdu)[0], + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->rah, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs1, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->mcs2, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->harq_pid, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi1, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->ndi2, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv1, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->rv2, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI2A_20MHz_4A_FDD_t *)&dci->dci_pdu[0])->TPC); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + } + } + + else + LOG_E(PHY,"Don't know how to handle TDD format 0 yet\n"); + + break; + + case format1E_2A_M10PRB: + + LOG_D(PHY,"DCI format1E_2A_M10PRB, rnti %x (%8x): harq_pid %d, rah %d, rb_alloc %x, mcs %d, rv %d, tpmi %d, ndi %d, dl_power_offset %d\n", + dci->rnti, + ((uint32_t *)&dci->dci_pdu)[0], + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->harq_pid, + //((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->tb_swap, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->rah, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->rballoc, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->mcs, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->rv, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->tpmi, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->ndi, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)&dci->dci_pdu[0])->dl_power_off + ); + + break; + + default: + LOG_E(PHY,"dci_tools.c: dump_dci, unknown format %d\n",dci->format); + return(-1); + } + + return(0); +} +#endif //(0) +#ifdef NR_PDCCH_DCI_TOOLS +int nr_extract_dci_info(PHY_VARS_NR_UE *ue, + uint8_t eNB_id, + lte_frame_type_t frame_type, + uint8_t dci_length, + void *dci_pdu, + NR_DCI_INFO_EXTRACTED_t *nr_pdci_info_extracted, + uint8_t dci_fields_sizes[48], + NR_DL_UE_HARQ_t *pdlsch0_harq, + NR_UE_DLSCH_t *pdlsch0, + NR_UE_ULSCH_t *ulsch0, + NR_DCI_format_t dci_format, + uint8_t nr_tti_rx, + uint16_t rnti, + uint16_t si_rnti, + uint16_t p_rnti, + uint16_t ra_rnti, + uint16_t tc_rnti, + uint16_t n_RB_ULBWP, + uint16_t n_RB_DLBWP) +{ +/* + * This function will extract the different elements of the dci pdu and interpret the values extracted to update correctly the parameters in: + * NR_DL_UE_HARQ_t *pdlsch0_harq, + * NR_UE_DLSCH_t *pdlsch0, + * + * We need to know the dci length and the dci_fields_sizes (array containing each field size in number of bits) + * In order to get the value of a specific field we will proceed as follows (let's have a look to an example: + * If the length of the pdu is 38 bits and the content of the dci_pdu is 0x3A8900789A (pdu is 11 1010 1000 1001 0000 0000 0111 1000 1001 1010) + * If the dci_fields_sizes is {0 0 1 0 0 0 0 0 0 13 0 1 0 0 0 0 0 0 0 0 0 0 5 1 2 4 2 0 0 0 2 3 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0} + * This means: + * number bits for carrier_ind field is 0 + * number bits for sul_ind_0_1 field is 0 + * number bits for identifier_dci_formats field is 0 + * number bits for slot_format_ind field is 0 + * number bits for pre_emption_ind field is 0 + * ... + * number bits for freq_dom_resource_assignment_DL field is 13 + * ... + * number bits for padding is 0 + * In order to extract the information of (e.g.) freq_dom_resource_assignment_DL field, + * we will do a left-shift of 1 position (because previous to this field, and according to the dci_fields_sizes array, there is only one non-empty field of size 1 bit) -> (1 1010 1000 1001 0000 0000 0111 1000 1001 1010 0) + * then we will do a right-shit of dci_length-13 positions -> (1 1010 1000 1001). And this is the content of the freq_dom_resource_assignment_DL field + * + * + * At the moment we have implemented: + * Format 0_0, that contains the following fields according to Specification 38.212 V15.1.1 Section 7.3.1 + * 2 IDENTIFIER_DCI_FORMATS: + * 8 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered + * 10 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, + * 15 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0 + * 22 MCS: + * 23 NDI: + * 24 RV: + * 25 HARQ_PROCESS_NUMBER: + * 29 TPC_PUSCH: + * 46 SUL_IND_0_0: + * 47 PADDING: (Note 2) If DCI format 0_0 is monitored in common search space + * + * Format 1_0, that contains the following fields + * 2 IDENTIFIER_DCI_FORMATS: + * 9 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: + * 10 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, + * 11 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0 + * 22 MCS: + * 23 NDI: + * 24 RV: + * 25 HARQ_PROCESS_NUMBER: + * 26 DAI: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI + * 30 TPC_PUCCH: + * 31 PUCCH_RESOURCE_IND: + * 32 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: + * 33 SHORT_MESSAGE_IND: 1 bit if crc scrambled with P-RNTI + * 47 PADDING: (Note 2) If DCI format 0_0 is monitored in common search space + * + */ + uint64_t pdu_bitmap = 0xFFFFFFFFFFFFFFFF; + pdu_bitmap = (pdu_bitmap << (64 - dci_length)) >> (64 - dci_length); // this variable will help to remove the bits of other fields when left-switching + uint8_t dci_field=0; + uint8_t sizes_count=0; + uint8_t left_shift=0; +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> Entering function nr_extract_dci_info() with dci_pdu=%llx with pdu_bitmap=%llx dci_length=%d\n",(*(uint64_t *)dci_pdu), pdu_bitmap, dci_length); + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> dci_fields_sizes {"); + for (int i=0; i<NBR_NR_DCI_FIELDS; i++) printf("%d ",dci_fields_sizes[i]); + printf("}\n"); +#endif + uint8_t prev_ndi = pdlsch0_harq->DCINdi; + uint16_t l_RB; + uint16_t start_RB; + uint16_t tmp_RIV; + uint16_t l_symbol; + uint16_t start_symbol; + uint16_t tmp_symbol; + + /* + * Some dci fields need to be interpreted before the others. + */ + if (dci_fields_sizes[HARQ_PROCESS_NUMBER] != 0) { // E.g: 25 HARQ_PROCESS_NUMBER (25 is the position in dci_fields_sizes array for field HARQ_PROCESS_NUMBER) + for (int i=0; i<=HARQ_PROCESS_NUMBER; i++) left_shift = left_shift + dci_fields_sizes[i]; + nr_pdci_info_extracted->harq_process_number = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[HARQ_PROCESS_NUMBER]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[HARQ_PROCESS_NUMBER])); + left_shift = 0; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->harq_process_number=%x\n",nr_pdci_info_extracted->harq_process_number); + #endif + } + + if ((dci_format == format1_0) || (dci_format == format1_1)) { + if (rnti==si_rnti) { + ue->dlsch_SI[eNB_id]->active = 1; + } else if (rnti==p_rnti) { + ue->dlsch_p[eNB_id]->active = 1; + } else if (rnti==ra_rnti) { + ue->dlsch_ra[eNB_id]->active = 1; + } else { + pdlsch0->active = 1; + } + pdlsch0->rnti = rnti; + pdlsch0_harq->codeword = 0; + pdlsch0_harq->Nl = 1; +// pdlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI; + pdlsch0_harq->dl_power_off = 1; //no power offset + + if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { + pdlsch0_harq->round = 0; + pdlsch0_harq->status = ACTIVE; + } else { + } + } + + for (dci_field=0; dci_field<NBR_NR_DCI_FIELDS; dci_field++) { + left_shift = left_shift + dci_fields_sizes[dci_field]; + if (dci_fields_sizes[dci_field] != 0){ + sizes_count = dci_fields_sizes[dci_field]; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> sizes_count = dci_fields_sizes[%d] = %d\n",dci_field,sizes_count); + #endif + + switch (dci_field){ + case 0: // 0 CARRIER_IND: (field defined for -,format0_1,-,format1_1,-,-,-,-) + // 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] + nr_pdci_info_extracted->carrier_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->carrier_ind=%x\n",nr_pdci_info_extracted->carrier_ind); +#endif + break; + case 1: // 1 SUL_IND_0_1: (field defined for -,format0_1,-,-,-,-,-,-) + nr_pdci_info_extracted->sul_ind_0_1 = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->sul_ind_0_1=%x\n",nr_pdci_info_extracted->sul_ind_0_1); +#endif + break; + + case 2: // 2 IDENTIFIER_DCI_FORMATS: (field defined for format0_0,format0_1,format1_0,format1_1,format2_0,format2_1,format2_2,format2_3) + // if format 0_0: The value of this bit field is always set to 0, indicating an UL DCI format (TS38.212 Section 7.3.1.1.1) + // if format 1_0: The value of this bit field is always set to 1, indicating a DL DCI format (TS38.212 Section 7.3.1.2.1) + nr_pdci_info_extracted->identifier_dci_formats = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->identifier_dci_formats=%x\n",nr_pdci_info_extracted->identifier_dci_formats); + #endif + break; + + case 3: // 3 SLOT_FORMAT_IND: (field defined for -,-,-,-,format2_0,-,-,-) + // size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213] + nr_pdci_info_extracted->slot_format_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->slot_format_ind=%x\n",nr_pdci_info_extracted->slot_format_ind); +#endif + break; + case 4: // 4 PRE_EMPTION_IND: (field defined for -,-,-,-,-,format2_1,-,-) + // size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits + nr_pdci_info_extracted->pre_emption_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->pre_emption_ind=%x\n",nr_pdci_info_extracted->pre_emption_ind); +#endif + break; + case 5: // 5 TPC_CMD_NUMBER: (field defined for -,-,-,-,-,-,format2_2,-) + // The parameter xxx provided by higher layers determines the index to the TPC command number for an UL of a cell. Each TPC command number is 2 bits + nr_pdci_info_extracted->tpc_cmd_number = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tpc_cmd_number=%x\n",nr_pdci_info_extracted->tpc_cmd_number); +#endif + break; + case 6: // 6 BLOCK_NUMBER: (field defined for -,-,-,-,-,-,-,format2_3) + // starting position of a block is determined by the parameter startingBitOfFormat2_3 + nr_pdci_info_extracted->block_number = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->block_number=%x\n",nr_pdci_info_extracted->block_number); +#endif + break; + case 7: // 7 BANDWIDTH_PART_IND: (field defined for -,format0_1,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->bandwidth_part_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->bandwidth_part_ind=%x\n",nr_pdci_info_extracted->bandwidth_part_ind); +#endif + break; + + case 8: // 8 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: (field defined for format0_0,format0_1,-,-,-,-,-,-) + // PUSCH hopping with resource allocation type 1 not considered + // According to 38.214 V15.1.0 Section 6.1.2.2 Two uplink resource allocation schemes, type 0 and type 1, are supported. + // The UE shall assume that when the scheduling PDCCH is received with DCI format 0_0, then uplink resource allocation type 1 is used. + nr_pdci_info_extracted->freq_dom_resource_assignment_UL = (uint16_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (dci_format == format0_1){ // uplink resource allocation type 0 or 1 can be used + } + if (dci_format == format0_0){ // only uplink resource allocation type 1 + // At the moment we are supporting only format 1_0 (and not format 1_1), so we only support resource allocation type 1 (and not type 0). + // For resource allocation type 1, the resource allocation field consists of a resource indication value (RIV): + // RIV = n_RB_ULBWP * (l_RB - 1) + start_RB if (l_RB - 1) <= floor (n_RB_ULBWP/2) + // RIV = n_RB_ULBWP * (n_RB_ULBWP - l_RB + 1) + (n_RB_ULBWP - 1 - start_RB) if (l_RB - 1) > floor (n_RB_ULBWP/2) + // the following two expressions apply only if (l_RB - 1) <= floor (n_RB_ULBWP/2) + l_RB = floor(nr_pdci_info_extracted->freq_dom_resource_assignment_DL/n_RB_ULBWP) + 1; + start_RB = nr_pdci_info_extracted->freq_dom_resource_assignment_DL%n_RB_ULBWP; + // if (l_RB - 1) > floor (n_RB_ULBWP/2) we need to recalculate them using the following lines + tmp_RIV = n_RB_ULBWP * (l_RB - 1) + start_RB; + if (tmp_RIV != nr_pdci_info_extracted->freq_dom_resource_assignment_DL) { // then (l_RB - 1) > floor (n_RB_ULBWP/2) and we need to recalculate l_RB and start_RB + l_RB = n_RB_ULBWP - l_RB + 2; + start_RB = n_RB_ULBWP - start_RB - 1; + } + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_rb = start_RB; + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->nb_rb = l_RB; + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->freq_dom_resource_assignment_UL=%x\n",nr_pdci_info_extracted->freq_dom_resource_assignment_UL); + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> l_RB=%d, start_RB=%d, n_RB_DLBWP=%d\n",l_RB,start_RB,n_RB_ULBWP); + #endif + break; + + case 9: // 9 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: (field defined for -,-,format1_0,format1_1,-,-,-,-) + // According to 38.214 V15.1.0 Section 5.1.2.2 Two downlink resource allocation schemes, type 0 and type 1, are supported. + // The UE shall assume that when the scheduling grant is received with DCI format 1_0, then downlink resource allocation type 1 is used. + nr_pdci_info_extracted->freq_dom_resource_assignment_DL = (uint16_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (dci_format == format1_1){ // uplink resource allocation type 0 or 1 can be used + } + if (dci_format == format1_0){ // only uplink resource allocation type 1 + // At the moment we are supporting only format 0_0 (and not format 0_1), so we only support resource allocation type 1 (and not type 0). + // For resource allocation type 1, the resource allocation field consists of a resource indication value (RIV): + // RIV = n_RB_DLBWP * (l_RB - 1) + start_RB if (l_RB - 1) <= floor (n_RB_DLBWP/2) + // RIV = n_RB_DLBWP * (n_RB_DLBWP - l_RB + 1) + (n_RB_DLBWP - 1 - start_RB) if (l_RB - 1) > floor (n_RB_DLBWP/2) + // the following two expressions apply only if (l_RB - 1) <= floor (n_RB_DLBWP/2) + l_RB = floor(nr_pdci_info_extracted->freq_dom_resource_assignment_DL/n_RB_DLBWP) + 1; + start_RB = nr_pdci_info_extracted->freq_dom_resource_assignment_DL%n_RB_DLBWP; + // if (l_RB - 1) > floor (n_RB_DLBWP/2) we need to recalculate them using the following lines + tmp_RIV = n_RB_DLBWP * (l_RB - 1) + start_RB; + if (tmp_RIV != nr_pdci_info_extracted->freq_dom_resource_assignment_DL) { // then (l_RB - 1) > floor (n_RB_DLBWP/2) and we need to recalculate l_RB and start_RB + l_RB = n_RB_DLBWP - l_RB + 2; + start_RB = n_RB_DLBWP - start_RB - 1; + } + pdlsch0_harq->nb_rb = l_RB; + pdlsch0->current_harq_pid = nr_pdci_info_extracted->harq_process_number; + pdlsch0->active = 1; + pdlsch0->rnti = rnti; + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->freq_dom_resource_assignment_DL=%x, RIV = %d\n",nr_pdci_info_extracted->freq_dom_resource_assignment_DL,nr_pdci_info_extracted->freq_dom_resource_assignment_DL); + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> l_RB=%d, start_RB=%d, n_RB_DLBWP=%d\n",l_RB,start_RB,n_RB_DLBWP); + /* + * The following commented code is used to verify that l_RB and start_RB are correctly calculated + * + * + printf("\ns_RB\t"); + n_RB_DLBWP = 20; + for (int k = 0 ; k < n_RB_DLBWP; k++) printf("%d\t",k); + printf("\nl_RB"); + for (int j = 1 ; j <= n_RB_DLBWP; j++){ // l_RB + printf("\n%d\t",j); + for (int i = 0 ; i < n_RB_DLBWP; i++) { // start_RB + if ((j-1) <= (floor(n_RB_DLBWP/2)) && ((j+i) <= n_RB_DLBWP)) { + tmp_RIV = n_RB_DLBWP * (j - 1) + i; + l_RB = floor(tmp_RIV/n_RB_DLBWP) + 1; + start_RB = tmp_RIV%n_RB_DLBWP; + printf("%d(%d,%d) ",tmp_RIV,l_RB,start_RB); + } + if ((j-1) > (floor(n_RB_DLBWP/2)) && ((j+i) <= n_RB_DLBWP)) { + tmp_RIV = n_RB_DLBWP * (n_RB_DLBWP - j + 1) + (n_RB_DLBWP - 1 - i); + //l_RB = floor(tmp_RIV/n_RB_DLBWP) + 1; + //start_RB = tmp_RIV%n_RB_DLBWP; + l_RB = n_RB_DLBWP - (floor(tmp_RIV/n_RB_DLBWP) + 1) + 2; + start_RB = n_RB_DLBWP - (tmp_RIV%n_RB_DLBWP) - 1; + printf("%d*(%d,%d) ",tmp_RIV,l_RB,start_RB); + } + } + }*/ + #endif + break; + + case 10: // 10 TIME_DOM_RESOURCE_ASSIGNMENT: (field defined for format0_0,format0_1,format1_0,format1_1,-,-,-,-) + // 0, 1, 2, 3, or 4 bits as defined in: + // Subclause 6.1.2.1 of [6, TS 38.214] for formats format0_0,format0_1 + // Subclause 5.1.2.1 of [6, TS 38.214] for formats format1_0,format1_1 + // The bitwidth for this field is determined as log2(I) bits, + // where I the number of entries in the higher layer parameter pusch-AllocationList + nr_pdci_info_extracted->time_dom_resource_assignment = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (dci_format == format0_0 || dci_format == format0_1){ // Subclause 6.1.2.1 of [6, TS 38.214] + + } + if (dci_format == format1_0 || dci_format == format1_1){ // Subclause 5.1.2.1 of [6, TS 38.214] + //the Time domain resource assignment field of the DCI provides a row index of a higher layer configured table pdsch-symbolAllocation + // FIXME! To clarify which parameters to update after reception of row index + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->time_dom_resource_assignment=%x\n",nr_pdci_info_extracted->time_dom_resource_assignment); + #endif + break; + + case 11: // 11 VRB_TO_PRB_MAPPING: (field defined for -,format0_1,format1_0,format1_1,-,-,-,-) + //0 bit if resource allocation type 0 + //1 bit if resource allocation type 1 + //Table 7.3.1.1.2-33: VRB-to-PRB mapping + // 0 Non-interleaved + // 1 Interleaved + nr_pdci_info_extracted->vrb_to_prb_mapping = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (nr_pdci_info_extracted->vrb_to_prb_mapping == 0) { // Non-interleaved + } else { // Interleaved + // format 0_1 defined in TS 38.211 Section 6.3.1.7 + // formats 1_0 and 1_1 not defined yet + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->vrb_to_prb_mapping=%x\n",nr_pdci_info_extracted->vrb_to_prb_mapping); + #endif + break; + + case 12: // 12 PRB_BUNDLING_SIZE_IND: (field defined for -,-,-,format1_1,-,-,-,-) + // 0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] + nr_pdci_info_extracted->prb_bundling_size_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->prb_bundling_size_ind=%x\n",nr_pdci_info_extracted->prb_bundling_size_ind); +#endif + break; + case 13: // 13 RATE_MATCHING_IND: (field defined for -,-,-,format1_1,-,-,-,-) + // 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set + nr_pdci_info_extracted->rate_matching_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->rate_matching_ind=%x\n",nr_pdci_info_extracted->rate_matching_ind); +#endif + break; + case 14: // 14 ZP_CSI_RS_TRIGGER: (field defined for -,-,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->zp_csi_rs_trigger = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->zp_csi_rs_trigger=%x\n",nr_pdci_info_extracted->zp_csi_rs_trigger); +#endif + break; + + case 15: // 15 FREQ_HOPPING_FLAG: (field defined for format0_0,format0_1,-,-,-,-,-,-) + // 0 bit if only resource allocation type 0 + // 1 bit otherwise, only applicable to resource allocation type 1, as defined in Subclause 6.3 of [6, TS 38.214] + nr_pdci_info_extracted->freq_hopping_flag = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (nr_pdci_info_extracted->freq_hopping_flag != 0) { // PUSCH frequency hopping is performed (only resource allocation type 1) + + } else { // PUSCH frequency hopping is not performed (only resource allocation type 1) + // At the moment PUSCH hopping is not implemented. We are considering that the bit is present and the value is '0' + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->freq_hopping_flag=%x\n",nr_pdci_info_extracted->freq_hopping_flag); + #endif + break; + + case 16: // 16 TB1_MCS: (field defined for -,-,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->tb1_mcs = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (nr_pdci_info_extracted->mcs < 29) pdlsch0_harq->mcs = nr_pdci_info_extracted->tb1_mcs; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb1_mcs=%x\n",nr_pdci_info_extracted->tb1_mcs); + #endif + break; + case 17: // 17 TB1_NDI: (field defined for -,-,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->tb1_ndi = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + pdlsch0_harq->DCINdi = nr_pdci_info_extracted->tb1_ndi; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb1_ndi=%x\n",nr_pdci_info_extracted->tb1_ndi); + #endif + break; + case 18: // 18 TB1_RV: (field defined for -,-,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->tb1_rv = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + pdlsch0_harq->rvidx = nr_pdci_info_extracted->tb1_rv; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb1_rv=%x\n",nr_pdci_info_extracted->tb1_rv); + #endif + break; + case 19: // 19 TB2_MCS: (field defined for -,-,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->tb2_mcs = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (nr_pdci_info_extracted->mcs < 29) pdlsch0_harq->mcs = nr_pdci_info_extracted->tb2_mcs; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb2_mcs=%x\n",nr_pdci_info_extracted->tb2_mcs); + #endif + break; + case 20: // 20 TB2_NDI: (field defined for -,-,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->tb2_ndi = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + pdlsch0_harq->DCINdi = nr_pdci_info_extracted->tb2_ndi; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb2_ndi=%x\n",nr_pdci_info_extracted->tb2_ndi); + #endif + break; + case 21: // 21 TB2_RV: (field defined for -,-,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->tb2_rv = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + pdlsch0_harq->rvidx = nr_pdci_info_extracted->tb2_rv; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb2_rv=%x\n",nr_pdci_info_extracted->tb2_rv); + #endif + break; + + case 22: // 22 MCS: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-) + nr_pdci_info_extracted->mcs = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (nr_pdci_info_extracted->mcs < 29) { + if (dci_format == format0_0 || dci_format == format0_1) + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->mcs = nr_pdci_info_extracted->mcs; + else + pdlsch0_harq->mcs = nr_pdci_info_extracted->mcs; + } else { + return(0); + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->mcs=%x\n",nr_pdci_info_extracted->mcs); + #endif + break; + + case 23: // 23 NDI: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-) + nr_pdci_info_extracted->ndi = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (dci_format == format0_0 || dci_format == format0_1) { + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi = nr_pdci_info_extracted->ndi; + if (ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_tx==1) { + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_tx=0; + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi= nr_pdci_info_extracted->ndi; + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->round = 0; + } else { + if (ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi != nr_pdci_info_extracted->ndi) { // new SDU opportunity + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi= nr_pdci_info_extracted->ndi; + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->round = 0; + } + } + } else { + if (rnti == tc_rnti) { //fix for standalone Contention Resolution Id + pdlsch0_harq->DCINdi = (uint8_t)-1; + } else { + if ((prev_ndi != nr_pdci_info_extracted->ndi) || (pdlsch0_harq->first_tx==1)) { + pdlsch0_harq->round = 0; + pdlsch0_harq->first_tx = 0; + pdlsch0_harq->status = ACTIVE; + } + pdlsch0_harq->DCINdi = nr_pdci_info_extracted->ndi; + } + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->ndi=%x\n",nr_pdci_info_extracted->ndi); + #endif + break; + + case 24: // 24 RV: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-) + nr_pdci_info_extracted->rv = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + if (dci_format == format0_0 || dci_format == format0_1) + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->rvidx = nr_pdci_info_extracted->rv; + else + pdlsch0_harq->rvidx = nr_pdci_info_extracted->rv; + if ((prev_ndi == nr_pdci_info_extracted->ndi) && (pdlsch0_harq->rvidx != 0)) { // NDI has not been toggled but rv was increased by eNB: retransmission + if (pdlsch0_harq->status == SCH_IDLE) { + // packet was actually decoded in previous transmission (ACK was missed by eNB) + // however, the round is not a good check as it might have been decoded in a retransmission prior to this one. + // skip pdsch decoding and report ack + pdlsch0->active = 0; + pdlsch0->harq_ack[nr_tti_rx].ack = 1; + pdlsch0->harq_ack[nr_tti_rx].harq_id = nr_pdci_info_extracted->harq_process_number; + pdlsch0->harq_ack[nr_tti_rx].send_harq_status = 1; + } else { // normal retransmission, nothing special to do + } + } else { + pdlsch0_harq->status = ACTIVE; + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->rv=%x\n",nr_pdci_info_extracted->rv); + #endif + break; + + case 25: // 25 HARQ_PROCESS_NUMBER: (field defined for format0_0,format0_1,format1_0,format1_1,-,-,-,-) + nr_pdci_info_extracted->harq_process_number = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + pdlsch0->current_harq_pid = nr_pdci_info_extracted->harq_process_number; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->harq_process_number=%x\n",nr_pdci_info_extracted->harq_process_number); + #endif + break; + + case 26: // 26 DAI: (field defined for -,-,format1_0,format1_1,-,-,-,-) + // For format1_0: 2 bits as defined in Subclause 9.1.3 at TS 38.213 + // For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI + // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI + // 0 otherwise + nr_pdci_info_extracted->dai = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + pdlsch0->harq_ack[nr_tti_rx].vDAI_DL = nr_pdci_info_extracted->dai+1; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->dai=%x\n",nr_pdci_info_extracted->dai); + #endif + break; + + case 27: // 27 FIRST_DAI: (field defined for -,format0_1,-,-,-,-,-,-) + // (1 or 2 bits) 1 bit for semi-static HARQ-ACK + nr_pdci_info_extracted->first_dai = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->first_dai=%x\n",nr_pdci_info_extracted->first_dai); +#endif + break; + case 28: // 28 SECOND_DAI: (field defined for -,format0_1,-,-,-,-,-,-) + // (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks + nr_pdci_info_extracted->second_dai = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->second_dai=%x\n",nr_pdci_info_extracted->second_dai); +#endif + break; + + case 29: // 29 TPC_PUSCH: (field defined for format0_0,format0_1,-,-,-,-,-,-) + // defined in Subclause 7.1.1 TS 38.213 + nr_pdci_info_extracted->tpc_pusch = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC = nr_pdci_info_extracted->tpc_pusch; + if (ue->ul_power_control_dedicated[eNB_id].accumulationEnabled == 1) { + ulsch0->f_pusch += delta_PUSCH_acc[ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC]; + } else { + ulsch0->f_pusch = delta_PUSCH_abs[ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC]; + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tpc_pusch=%x\n",nr_pdci_info_extracted->tpc_pusch); + #endif + break; + + case 30: // 30 TPC_PUCCH: (field defined for -,-,format1_0,format1_1,-,-,-,-) + // defined in Subclause 7.2.1 TS 38.213 + nr_pdci_info_extracted->tpc_pucch = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + pdlsch0_harq->delta_PUCCH = delta_PUCCH_lut[nr_pdci_info_extracted->tpc_pucch &3]; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tpc_pucch=%x\n",nr_pdci_info_extracted->tpc_pucch); + #endif + break; + + case 31: // 31 PUCCH_RESOURCE_IND: (field defined for -,-,format1_0,format1_1,-,-,-,-) + // defined in Subclause 9.2.3 TS 38.213 + // PUCCH_RESOURCE_IND points to PUCCH-ResourceId, but PUCCH-ResourceId is not defined yet + nr_pdci_info_extracted->pucch_resource_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->pucch_resource_ind=%x\n",nr_pdci_info_extracted->pucch_resource_ind); + #endif + break; + + case 32: // 32 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: (field defined for -,-,format1_0,format1_1,-,-,-,-) + // defined in Subclause 9.2.3 TS 38.213 + // PDSCH_TO_HARQ_FEEDBACK_TIME_IND points to DL-data-DL-acknowledgement, but DL-data-DL-acknowledgement is not defined yet + nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind=%x\n",nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind); + #endif + break; + + case 33: // 33 SHORT_MESSAGE_IND: (field defined for -,-,format1_0,-,-,-,-,-) + // 1 bit if crc scrambled with P-RNTI + if (rnti == p_rnti) { + nr_pdci_info_extracted->short_message_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); + // short message indication flag not implemented in NR_UE_DLSCH_t + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->short_message_ind=%x\n",nr_pdci_info_extracted->short_message_ind); + #endif + break; + + case 34: // 34 SRS_RESOURCE_IND: (field defined for -,format0_1,-,-,-,-,-,-) + nr_pdci_info_extracted->srs_resource_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->srs_resource_ind=%x\n",nr_pdci_info_extracted->srs_resource_ind); +#endif + break; + case 35: // 35 PRECOD_NBR_LAYERS: (field defined for -,format0_1,-,-,-,-,-,-) + nr_pdci_info_extracted->precod_nbr_layers = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->precod_nbr_layers=%x\n",nr_pdci_info_extracted->precod_nbr_layers); +#endif + break; + case 36: // 36 ANTENNA_PORTS: (field defined for -,format0_1,-,format1_1,-,-,-,-) + nr_pdci_info_extracted->antenna_ports = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->antenna_ports=%x\n",nr_pdci_info_extracted->antenna_ports); +#endif + break; + case 37: // 37 TCI: (field defined for -,-,-,format1_1,-,-,-,-) + // 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits + nr_pdci_info_extracted->tci = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tci=%x\n",nr_pdci_info_extracted->tci); +#endif + break; + case 38: // 38 SRS_REQUEST: (field defined for -,format0_1,-,format1_1,-,-,-,format2_3) + nr_pdci_info_extracted->srs_request = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->srs_request=%x\n",nr_pdci_info_extracted->srs_request); +#endif + break; + case 39: // 39 TPC_CMD_NUMBER_FORMAT2_3: (field defined for -,-,-,-,-,-,-,format2_3) + nr_pdci_info_extracted->tpc_cmd_number_format2_3 = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tpc_cmd_number_format2_3=%x\n",nr_pdci_info_extracted->tpc_cmd_number_format2_3); +#endif + break; + case 40: // 40 CSI_REQUEST: (field defined for -,format0_1,-,-,-,-,-,-) + nr_pdci_info_extracted->csi_request = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->csi_request=%x\n",nr_pdci_info_extracted->csi_request); +#endif + break; + case 41: // 41 CBGTI: (field defined for -,format0_1,-,format1_1,-,-,-,-) + // 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH + nr_pdci_info_extracted->cbgti = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->cbgti=%x\n",nr_pdci_info_extracted->cbgti); +#endif + break; + case 42: // 42 CBGFI: (field defined for -,-,-,format1_1,-,-,-,-) + // 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator + nr_pdci_info_extracted->cbgfi = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->cbgfi=%x\n",nr_pdci_info_extracted->cbgfi); +#endif + break; + case 43: // 43 PTRS_DMRS: (field defined for -,format0_1,-,-,-,-,-,-) + nr_pdci_info_extracted->ptrs_dmrs = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->ptrs_dmrs=%x\n",nr_pdci_info_extracted->ptrs_dmrs); +#endif + break; + case 44: // 44 BETA_OFFSET_IND: (field defined for -,format0_1,-,-,-,-,-,-) + nr_pdci_info_extracted->beta_offset_ind = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->beta_offset_ind=%x\n",nr_pdci_info_extracted->beta_offset_ind); +#endif + break; + case 45: // 45 DMRS_SEQ_INI: (field defined for -,format0_1,-,format1_1,-,-,-,-) + // 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding is larger than the number of bits for DCI format 0_0 before padding; 0 bit otherwise + nr_pdci_info_extracted->dmrs_seq_ini = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->dmrs_seq_ini=%x\n",nr_pdci_info_extracted->dmrs_seq_ini); +#endif + break; + case 46: // 46 SUL_IND_0_0: (field defined for format0_0,-,-,-,-,-,-,-) + nr_pdci_info_extracted->sul_ind_0_0 = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->sul_ind_0_0=%x\n",nr_pdci_info_extracted->sul_ind_0_0); +#endif + break; + case 47: // 47 PADDING: (field defined for format0_0,-,format1_0,-,-,-,-,-) + // (Note 2) If DCI format 0_0 is monitored in common search space + nr_pdci_info_extracted->padding = (uint16_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[dci_field]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field])); +#ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->padding=%x\n",nr_pdci_info_extracted->padding); +#endif + break; + } + } + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> Ending function nr_extract_dci_info()\n"); + #endif + return(1); +} +#endif + +#if 0 +void extract_dci1A_info(uint8_t N_RB_DL, lte_frame_type_t frame_type, void *dci_pdu, DCI_INFO_EXTRACTED_t *pdci_info_extarcted) +{ + uint8_t harq_pid=0; + uint32_t rballoc=0; + uint8_t vrb_type=0; + uint8_t mcs=0; + uint8_t rv=0; + uint8_t ndi=0; + uint8_t TPC=0; + + uint8_t dai=0; + + switch (N_RB_DL) { + case 6: + if (frame_type == TDD) { + vrb_type = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rballoc; + rv = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rv; + ndi = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->ndi; + TPC = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid; + dai = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->dai; + // printf("TDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC); + } else { + vrb_type = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rv; + ndi = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->ndi; + TPC = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->harq_pid; + //printf("FDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC); + } + break; + + case 25: + + if (frame_type == TDD) { + vrb_type = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rballoc; + rv = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rv; + ndi = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->ndi; + TPC = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid; + dai = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->dai; + //printf("TDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC); + } else { + vrb_type = ((DCI1A_5MHz_FDD_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_5MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_5MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1A_5MHz_FDD_t *)dci_pdu)->rv; + ndi = ((DCI1A_5MHz_FDD_t *)dci_pdu)->ndi; + TPC = ((DCI1A_5MHz_FDD_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_5MHz_FDD_t *)dci_pdu)->harq_pid; + //printf("FDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC); + } + + break; + + case 50: + if (frame_type == TDD) { + vrb_type = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rballoc; + rv = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rv; + ndi = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->ndi; + TPC = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->harq_pid; + dai = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->dai; + // printf("TDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC); + } else { + vrb_type = ((DCI1A_10MHz_FDD_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_10MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_10MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1A_10MHz_FDD_t *)dci_pdu)->rv; + ndi = ((DCI1A_10MHz_FDD_t *)dci_pdu)->ndi; + TPC = ((DCI1A_10MHz_FDD_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_10MHz_FDD_t *)dci_pdu)->harq_pid; + //printf("FDD 1A: mcs %d, vrb_type %d, rballoc %x,ndi %d, rv %d, TPC %d\n",mcs,vrb_type,rballoc,ndi,rv,TPC); + } + break; + + case 100: + if (frame_type == TDD) { + vrb_type = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rballoc; + rv = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rv; + ndi = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->ndi; + TPC = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->harq_pid; + dai = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->dai; + // printf("TDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC); + } else { + vrb_type = ((DCI1A_20MHz_FDD_t *)dci_pdu)->vrb_type; + mcs = ((DCI1A_20MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1A_20MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1A_20MHz_FDD_t *)dci_pdu)->rv; + ndi = ((DCI1A_20MHz_FDD_t *)dci_pdu)->ndi; + TPC = ((DCI1A_20MHz_FDD_t *)dci_pdu)->TPC; + harq_pid = ((DCI1A_20MHz_FDD_t *)dci_pdu)->harq_pid; + //printf("FDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC); + } + break; + } + + pdci_info_extarcted->vrb_type = vrb_type; + pdci_info_extarcted->mcs1 = mcs; + pdci_info_extarcted->rballoc = rballoc; + pdci_info_extarcted->rv1 = rv; + pdci_info_extarcted->ndi1 = ndi; + pdci_info_extarcted->TPC = TPC; + pdci_info_extarcted->harq_pid = harq_pid; + pdci_info_extarcted->dai = dai; +} + +void extract_dci1C_info(uint8_t N_RB_DL, lte_frame_type_t frame_type, void *dci_pdu, DCI_INFO_EXTRACTED_t *pdci_info_extarcted) +{ + + uint32_t rballoc=0; + uint8_t mcs=0; + + switch (N_RB_DL) { + case 6: + mcs = ((DCI1C_5MHz_t *)dci_pdu)->mcs; + rballoc = conv_1C_RIV(((DCI1C_5MHz_t *)dci_pdu)->rballoc,6); + + break; + + case 25: + mcs = ((DCI1C_5MHz_t *)dci_pdu)->mcs; + rballoc = conv_1C_RIV(((DCI1C_5MHz_t *)dci_pdu)->rballoc,6); + + break; + + case 50: + mcs = ((DCI1C_10MHz_t *)dci_pdu)->mcs; + rballoc = conv_1C_RIV(((DCI1C_10MHz_t *)dci_pdu)->rballoc,6); + + break; + + case 100: + mcs = ((DCI1C_20MHz_t *)dci_pdu)->mcs; + rballoc = conv_1C_RIV(((DCI1C_20MHz_t *)dci_pdu)->rballoc,6); + break; + + default: + AssertFatal(0,"Format 1C: Unknown N_RB_DL %d\n",N_RB_DL); + break; + } + + pdci_info_extarcted->mcs1 = mcs; + pdci_info_extarcted->rballoc = rballoc; +} + +void extract_dci1_info(uint8_t N_RB_DL, lte_frame_type_t frame_type, void *dci_pdu, DCI_INFO_EXTRACTED_t *pdci_info_extarcted) +{ + + uint32_t rballoc=0; + uint8_t mcs=0; + uint8_t rah=0; + uint8_t rv=0; + uint8_t TPC=0; + uint8_t ndi=0; + uint8_t harq_pid=0; + + switch (N_RB_DL) { + case 6: + if (frame_type == TDD) { + mcs = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rah; + rv = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rv; + TPC = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->TPC; + ndi = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->ndi; + harq_pid = ((DCI1_1_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->mcs; + rah = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rah; + rballoc = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rv; + TPC = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->TPC; + ndi = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->ndi; + harq_pid = ((DCI1_1_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 25: + if (frame_type == TDD) { + mcs = ((DCI1_5MHz_TDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1_5MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI1_5MHz_TDD_t *)dci_pdu)->rah; + rv = ((DCI1_5MHz_TDD_t *)dci_pdu)->rv; + TPC = ((DCI1_5MHz_TDD_t *)dci_pdu)->TPC; + ndi = ((DCI1_5MHz_TDD_t *)dci_pdu)->ndi; + harq_pid = ((DCI1_5MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs = ((DCI1_5MHz_FDD_t *)dci_pdu)->mcs; + rah = ((DCI1_5MHz_FDD_t *)dci_pdu)->rah; + rballoc = ((DCI1_5MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1_5MHz_FDD_t *)dci_pdu)->rv; + TPC = ((DCI1_5MHz_FDD_t *)dci_pdu)->TPC; + ndi = ((DCI1_5MHz_FDD_t *)dci_pdu)->ndi; + harq_pid = ((DCI1_5MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 50: + if (frame_type == TDD) { + mcs = ((DCI1_10MHz_TDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1_10MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI1_10MHz_TDD_t *)dci_pdu)->rah; + rv = ((DCI1_10MHz_TDD_t *)dci_pdu)->rv; + TPC = ((DCI1_10MHz_TDD_t *)dci_pdu)->TPC; + ndi = ((DCI1_10MHz_TDD_t *)dci_pdu)->ndi; + harq_pid = ((DCI1_10MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs = ((DCI1_10MHz_FDD_t *)dci_pdu)->mcs; + rah = ((DCI1_10MHz_FDD_t *)dci_pdu)->rah; + rballoc = ((DCI1_10MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1_10MHz_FDD_t *)dci_pdu)->rv; + TPC = ((DCI1_10MHz_FDD_t *)dci_pdu)->TPC; + ndi = ((DCI1_10MHz_FDD_t *)dci_pdu)->ndi; + harq_pid = ((DCI1_10MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + + case 100: + if (frame_type == TDD) { + mcs = ((DCI1_20MHz_TDD_t *)dci_pdu)->mcs; + rballoc = ((DCI1_20MHz_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI1_20MHz_TDD_t *)dci_pdu)->rah; + rv = ((DCI1_20MHz_TDD_t *)dci_pdu)->rv; + TPC = ((DCI1_20MHz_TDD_t *)dci_pdu)->TPC; + ndi = ((DCI1_20MHz_TDD_t *)dci_pdu)->ndi; + harq_pid = ((DCI1_20MHz_TDD_t *)dci_pdu)->harq_pid; + } else { + mcs = ((DCI1_20MHz_FDD_t *)dci_pdu)->mcs; + rah = ((DCI1_20MHz_FDD_t *)dci_pdu)->rah; + rballoc = ((DCI1_20MHz_FDD_t *)dci_pdu)->rballoc; + rv = ((DCI1_20MHz_FDD_t *)dci_pdu)->rv; + TPC = ((DCI1_20MHz_FDD_t *)dci_pdu)->TPC; + ndi = ((DCI1_20MHz_FDD_t *)dci_pdu)->ndi; + harq_pid = ((DCI1_20MHz_FDD_t *)dci_pdu)->harq_pid; + } + + break; + } + + pdci_info_extarcted->mcs1 = mcs; + pdci_info_extarcted->rah = rah; + pdci_info_extarcted->rballoc = rballoc; + pdci_info_extarcted->rv1 = rv; + pdci_info_extarcted->TPC = TPC; + pdci_info_extarcted->ndi1 = ndi; + pdci_info_extarcted->harq_pid = harq_pid; + +} + +void extract_dci2_info(uint8_t N_RB_DL, lte_frame_type_t frame_type, uint8_t nb_antenna_ports_eNB, void *dci_pdu, DCI_INFO_EXTRACTED_t *pdci_info_extarcted) +{ + + uint32_t rballoc=0; + uint8_t rah=0; + uint8_t mcs1=0; + uint8_t mcs2=0; + uint8_t rv1=0; + uint8_t rv2=0; + uint8_t ndi1=0; + uint8_t ndi2=0; + uint8_t tbswap=0; + uint8_t tpmi=0; + uint8_t harq_pid=0; + uint8_t TPC=0; + + switch (N_RB_DL) { + + case 6: + if (nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + rah = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi2; + } else { + rah = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->ndi2; + } + } else if (nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + rah = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->ndi2; + } else { + rah = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->ndi2; + } + } else { + LOG_E(PHY,"UE: Format2 DCI: unsupported number of TX antennas %d\n",nb_antenna_ports_eNB); + } + + break; + + case 25: + if (nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + rah = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi2; + } else { + rah = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->ndi2; + } + } else if (nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + rah = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi2; + } else { + rah = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->ndi2; + } + } else { + LOG_E(PHY,"UE: Format2 DCI: unsupported number of TX antennas %d\n",nb_antenna_ports_eNB); + } + + break; + + case 50: + if (nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + rah = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->ndi2; + } else { + rah = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->ndi2; + } + } else if (nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + rah = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->ndi2; + } else { + rah = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->ndi2; + } + } else { + LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",nb_antenna_ports_eNB); + } + + break; + + case 100: + if (nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + rah = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->ndi2; + } else { + rah = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->ndi2; + } + } else if (nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + rah = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->ndi2; + } else { + rah = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->rah; + mcs1 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->rv2; + harq_pid = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->TPC; + ndi1 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->ndi2; + } + } else { + LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",nb_antenna_ports_eNB); + } + + break; + } + + pdci_info_extarcted->rah = rah; + pdci_info_extarcted->mcs1 = mcs1; + pdci_info_extarcted->mcs2 = mcs2; + pdci_info_extarcted->rv1 = rv1; + pdci_info_extarcted->rv2 = rv2; + pdci_info_extarcted->harq_pid = harq_pid; + pdci_info_extarcted->rballoc = rballoc; + pdci_info_extarcted->tb_swap = tbswap; + pdci_info_extarcted->tpmi = tpmi; + pdci_info_extarcted->TPC = TPC; + pdci_info_extarcted->ndi1 = ndi1; + pdci_info_extarcted->ndi2 = ndi2; + +} + +void extract_dci2A_info(uint8_t N_RB_DL, lte_frame_type_t frame_type, uint8_t nb_antenna_ports_eNB, void *dci_pdu, DCI_INFO_EXTRACTED_t *pdci_info_extarcted) +{ + + uint32_t rballoc=0; + uint8_t rah=0; + uint8_t mcs1=0; + uint8_t mcs2=0; + uint8_t rv1=0; + uint8_t rv2=0; + uint8_t ndi1=0; + uint8_t ndi2=0; + uint8_t tbswap=0; + uint8_t tpmi=0; + uint8_t harq_pid=0; + uint8_t TPC=0; + + AssertFatal( (nb_antenna_ports_eNB == 2) || (nb_antenna_ports_eNB == 4), "unsupported nb_antenna_ports_eNB %d\n", nb_antenna_ports_eNB); + switch (N_RB_DL) { + + case 6: + if (nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; + TPC = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->TPC; + } else { + mcs1 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; + TPC = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->TPC; + } + } else if (nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->TPC; + } else { + mcs1 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->rballoc; + rv1 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->TPC; + } + } + + break; + + case 25: + if (nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; + TPC = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->TPC; + } else { + mcs1 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; + TPC = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->TPC; + } + } else if (nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->TPC; + } else { + mcs1 = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->TPC; + } + } + break; + + case 50: + if (nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->tb_swap; + TPC = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->TPC; + } else { + mcs1 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->tb_swap; + TPC = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->TPC; + } + } else if (nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->TPC; + } else { + mcs1 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->TPC; + } + } + + break; + + case 100: + if (nb_antenna_ports_eNB == 2) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->tb_swap; + TPC = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->TPC; + } else { + mcs1 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->tb_swap; + TPC = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->TPC; + } + } else if (nb_antenna_ports_eNB == 4) { + if (frame_type == TDD) { + mcs1 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->TPC; + } else { + mcs1 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->mcs1; + mcs2 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->mcs2; + rballoc = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->rballoc; + rah = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->rah; + rv1 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->rv1; + rv2 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->rv2; + ndi1 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->ndi1; + ndi2 = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->ndi2; + harq_pid = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->harq_pid; + tbswap = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->tb_swap; + tpmi = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->tpmi; + TPC = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->TPC; + } + } + + break; + } + + pdci_info_extarcted->mcs1 = mcs1; + pdci_info_extarcted->mcs2 = mcs2; + pdci_info_extarcted->rballoc = rballoc; + pdci_info_extarcted->rah = rah; + pdci_info_extarcted->rv1 = rv1; + pdci_info_extarcted->rv2 = rv2; + pdci_info_extarcted->ndi1 = ndi1; + pdci_info_extarcted->ndi2 = ndi2; + pdci_info_extarcted->harq_pid = harq_pid; + pdci_info_extarcted->tb_swap = tbswap; + pdci_info_extarcted->TPC = TPC; + pdci_info_extarcted->tpmi = tpmi; +} + +int check_dci_format1_1a_coherency(DCI_format_t dci_format, + uint8_t N_RB_DL, + uint16_t rnti, + uint16_t tc_rnti, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint32_t frame, + uint8_t nr_tti_rx, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + NR_DL_UE_HARQ_t *pdlsch0_harq) +{ + uint8_t harq_pid = pdci_info_extarcted->harq_pid; + uint32_t rballoc = pdci_info_extarcted->rballoc; + uint8_t mcs1 = pdci_info_extarcted->mcs1; + uint8_t TPC = pdci_info_extarcted->TPC; + uint8_t rah = pdci_info_extarcted->rah; +#ifdef DEBUG_DCI + uint8_t rv1 = pdci_info_extarcted->rv1; + uint8_t ndi1 = pdci_info_extarcted->ndi1; +#endif + + uint8_t NPRB = 0; + long long int RIV_max = 0; + +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1-1A] AbsSubframe %d.%d dci_format %d\n", frame, nr_tti_rx, dci_format); + LOG_I(PHY,"[DCI-FORMAT-1-1A] rnti %x\n", rnti); + LOG_I(PHY,"[DCI-FORMAT-1-1A] harq_pid %d\n", harq_pid); + LOG_I(PHY,"[DCI-FORMAT-1-1A] rah %d\n", rah); + LOG_I(PHY,"[DCI-FORMAT-1-1A] rballoc %x\n", rballoc); + LOG_I(PHY,"[DCI-FORMAT-1-1A] mcs1 %d\n", mcs1); + LOG_I(PHY,"[DCI-FORMAT-1-1A] rv1 %d\n", rv1); + LOG_I(PHY,"[DCI-FORMAT-1-1A] ndi1 %d\n", ndi1); + LOG_I(PHY,"[DCI-FORMAT-1-1A] TPC %d\n", TPC); +#endif + + + // I- check dci content minimum coherency + if( ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) && harq_pid > 0) + { + return(0); + } + + if(harq_pid>=8) + { + LOG_I(PHY,"bad harq id \n"); + return(0); + } + + if(dci_format == format1 && ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) ) + { + LOG_I(PHY,"bad dci format \n"); + return(0); + } + + + if( mcs1 > 28) + { + if(pdlsch0_harq->round == 0) + { + LOG_I(PHY,"bad dci mcs + round \n"); + return(0); + } + + if((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) + { + LOG_I(PHY,"bad dci mcs + rnti \n"); + return(0); + } + } + + if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) + { + NPRB = (TPC&1) + 2; + switch (N_RB_DL) { + case 6: + RIV_max = RIV_max6; + break; + case 25: + RIV_max = RIV_max25; + break; + case 50: + RIV_max = RIV_max50; + break; + case 100: + RIV_max = RIV_max100; + break; + } + } + /*else + { + switch (N_RB_DL) { + case 6: + NPRB = RIV2nb_rb_LUT6[rballoc];//NPRB; + if(rah) + RIV_max = RIV_max6; + else + RIV_max = 0x3F; + break; + case 25: + NPRB = RIV2nb_rb_LUT25[rballoc];//NPRB; + if(rah) + RIV_max = RIV_max25; + else + RIV_max = 0x1FFF; + break; + case 50: + NPRB = RIV2nb_rb_LUT50[rballoc];//NPRB; + if(rah) + RIV_max = RIV_max50; + else + RIV_max = 0x1FFFF; + break; + case 100: + NPRB = RIV2nb_rb_LUT100[rballoc];//NPRB; + if(rah) + RIV_max = RIV_max100; + else + RIV_max = 0x1FFFFFF; + break; + } + }*/ + + + if(dci_format == format1) + { + NPRB = conv_nprb(rah, rballoc, N_RB_DL); + } + + /* + if(rballoc > RIV_max) + { + LOG_I(PHY,"bad dci rballoc rballoc %d RIV_max %lld \n",rballoc, RIV_max); + // DCI false detection + return(0); + } + */ + + if(NPRB == 0) + { + // DCI false detection + LOG_I(PHY,"bad NPRB = 0 \n"); + return(0); + } + + // this a retransmission + if(pdlsch0_harq->round>0) + { + // compare old TBS to new TBS + if((mcs1<29) && (pdlsch0_harq->TBS != TBStable[get_I_TBS(mcs1)][NPRB-1])) + { + // this is an eNB issue + // retransmisison but old and new TBS are different !!! + // work around, consider it as a new transmission + LOG_E(PHY,"Format1A Retransmission but TBS are different: consider it as new transmission !!! \n"); + pdlsch0_harq->round = 0; + //return(0); // ?? to cross check + } + } + + return(1); +} + +int check_dci_format1c_coherency(uint8_t N_RB_DL, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + uint16_t rnti, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + NR_DL_UE_HARQ_t *pdlsch0_harq) +{ + uint32_t rballoc = pdci_info_extarcted->rballoc; + + uint8_t NPRB = 0; + uint32_t RIV_max = 0; + + // I- check dci content minimum coherency + + if((rnti!=si_rnti) && (rnti!=p_rnti) && (rnti!=ra_rnti)) + return(0); + + switch (N_RB_DL) { + case 6: + NPRB = RIV2nb_rb_LUT6[rballoc];//NPRB; + RIV_max = RIV_max6; + break; + case 25: + NPRB = RIV2nb_rb_LUT25[rballoc];//NPRB; + RIV_max = RIV_max25; + break; + case 50: + NPRB = RIV2nb_rb_LUT50[rballoc];//NPRB; + RIV_max = RIV_max50; + break; + case 100: + NPRB = RIV2nb_rb_LUT100[rballoc];//NPRB; + RIV_max = RIV_max100; + break; + } + + if(rballoc > RIV_max) + { + // DCI false detection + return(0); + } + + if(NPRB == 0) + { + // DCI false detection + return(0); + } + + return(1); +} + +int check_dci_format2_2a_coherency(DCI_format_t dci_format, + uint8_t N_RB_DL, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + uint16_t rnti, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + NR_DL_UE_HARQ_t *pdlsch0_harq, + NR_DL_UE_HARQ_t *pdlsch1_harq) +{ + uint8_t rah = pdci_info_extarcted->rah; + uint8_t mcs1 = pdci_info_extarcted->mcs1; + uint8_t mcs2 = pdci_info_extarcted->mcs2; + uint8_t rv1 = pdci_info_extarcted->rv1; + uint8_t rv2 = pdci_info_extarcted->rv2; + uint8_t harq_pid = pdci_info_extarcted->harq_pid; + uint32_t rballoc = pdci_info_extarcted->rballoc; + +#ifdef DEBUG_DCI + uint8_t ndi1 = pdci_info_extarcted->ndi1; + uint8_t ndi2 = pdci_info_extarcted->ndi2; +#endif + + uint8_t NPRB = 0; + long long RIV_max = 0; + +#ifdef DEBUG_DCI + LOG_I(PHY, "extarcted dci - dci_format %d \n", dci_format); + LOG_I(PHY, "extarcted dci - rnti %d \n", rnti); + LOG_I(PHY, "extarcted dci - rah %d \n", rah); + LOG_I(PHY, "extarcted dci - mcs1 %d \n", mcs1); + LOG_I(PHY, "extarcted dci - mcs2 %d \n", mcs2); + LOG_I(PHY, "extarcted dci - rv1 %d \n", rv1); + LOG_I(PHY, "extarcted dci - rv2 %d \n", rv2); + //LOG_I(PHY, "extarcted dci - ndi1 %d \n", ndi1); + //LOG_I(PHY, "extarcted dci - ndi2 %d \n", ndi2); + LOG_I(PHY, "extarcted dci - rballoc %x \n", rballoc); + LOG_I(PHY, "extarcted dci - harq pid %d \n", harq_pid); + LOG_I(PHY, "extarcted dci - round0 %d \n", pdlsch0_harq->round); + LOG_I(PHY, "extarcted dci - round1 %d \n", pdlsch1_harq->round); +#endif + + // I- check dci content minimum coherency + if(harq_pid>=8) + { + LOG_I(PHY,"bad harq pid\n"); + return(0); + } + + if( (rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti) ) + { + LOG_I(PHY,"bad rnti\n"); + return(0); + } + + + if( mcs1 > 28) + { + if(pdlsch0_harq->round == 0) + { + LOG_I(PHY,"bad mcs1\n"); + return(0); + } + } + + if( mcs2 > 28) + { + if(pdlsch1_harq->round == 0) + { + LOG_I(PHY,"bad mcs2\n"); + return(0); + } + + } + + + if((pdlsch0_harq->round == 0) && (rv1 > 0) && (mcs1 != 0)) + { + // DCI false detection + LOG_I(PHY,"bad rv1\n"); + return(0); + } + + if((pdlsch1_harq->round == 0) && (rv2 > 0) && (mcs2 != 0)) + { + // DCI false detection + LOG_I(PHY,"bad rv2\n"); + return(0); + } + + + switch (N_RB_DL) { + case 6: + if (rah == 0) + { + //RBG = 1; + RIV_max = 0x3F; + } + else + { + RIV_max = RIV_max6; + } + break; + case 25: + if (rah == 0) + { + //RBG = 2; + RIV_max = 0x1FFF; + } + else + { + RIV_max = RIV_max25; + } + break; + case 50: + if (rah == 0) + { + //RBG = 3; + RIV_max = 0x1FFFF; + } + else + { + RIV_max = RIV_max50; + } + break; + case 100: + if (rah == 0) + { + //RBG = 4; + RIV_max = 0x1FFFFFF; + } + else + { + RIV_max = RIV_max100; + } + break; + } + + NPRB = conv_nprb(rah, + rballoc, + N_RB_DL); + + + + if( (rballoc > RIV_max) && (rah == 1) ) + { + // DCI false detection + LOG_I(PHY,"bad rballoc %d RIV_max %lld\n", rballoc, RIV_max); + return(0); + } + + if(NPRB == 0) + { + // DCI false detection + LOG_I(PHY,"bad NPRB\n"); + return(0); + } + + return(1); +} + +void compute_llr_offset(NR_DL_FRAME_PARMS *frame_parms, + NR_UE_PDCCH *pdcch_vars, + NR_UE_PDSCH *pdsch_vars, + NR_DL_UE_HARQ_t *dlsch0_harq, + uint8_t nb_rb_alloc, + uint8_t nr_tti_rx) +{ + uint32_t pbch_pss_sss_re; + uint32_t crs_re; + uint32_t granted_re; + uint32_t data_re; + uint32_t llr_offset; + uint8_t symbol; + uint8_t symbol_mod; + + pdsch_vars->llr_offset[pdcch_vars->num_pdcch_symbols] = 0; + + //LOG_I(PHY,"compute_llr_offset: nb RB %d - Qm %d \n", nb_rb_alloc, dlsch0_harq->Qm); + + //dlsch0_harq->rb_alloc_even; + //dlsch0_harq->rb_alloc_odd; + + for(symbol=pdcch_vars->num_pdcch_symbols; symbol<frame_parms->symbols_per_tti; symbol++) + { + symbol_mod = (symbol >= (7-frame_parms->Ncp))? (symbol-(7-frame_parms->Ncp)) : symbol; + if((symbol_mod == 0) || symbol_mod == (4-frame_parms->Ncp)) + { + if (frame_parms->mode1_flag==0) + crs_re = 4; + else + crs_re = 2; + } + else + { + crs_re = 0; + } + + granted_re = nb_rb_alloc * (12-crs_re); + pbch_pss_sss_re = adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,dlsch0_harq->Qm,nr_tti_rx,symbol); + pbch_pss_sss_re = (double)pbch_pss_sss_re * ((double)(12-crs_re)/12); + data_re = granted_re - pbch_pss_sss_re; + llr_offset = data_re * dlsch0_harq->Qm * 2; + + pdsch_vars->llr_length[symbol] = data_re; + if(symbol < (frame_parms->symbols_per_tti-1)) + pdsch_vars->llr_offset[symbol+1] = pdsch_vars->llr_offset[symbol] + llr_offset; + + //LOG_I(PHY,"Granted Re nr_tti_rx %d / symbol %d => %d (%d RBs)\n", nr_tti_rx, symbol_mod, granted_re,dlsch0_harq->nb_rb); + //LOG_I(PHY,"Pbch/PSS/SSS Re nr_tti_rx %d / symbol %d => %d \n", nr_tti_rx, symbol_mod, pbch_pss_sss_re); + //LOG_I(PHY,"CRS Re Per PRB nr_tti_rx %d / symbol %d => %d \n", nr_tti_rx, symbol_mod, crs_re); + //LOG_I(PHY,"Data Re nr_tti_rx %d / symbol %d => %d \n", nr_tti_rx, symbol_mod, data_re); + + + + //LOG_I(PHY,"Data Re nr_tti_rx %d-symbol %d => llr length %d, llr offset %d \n", nr_tti_rx, symbol, + // pdsch_vars->llr_length[symbol], pdsch_vars->llr_offset[symbol]); + } +} +void prepare_dl_decoding_format1_1A(DCI_format_t dci_format, + uint8_t N_RB_DL, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + NR_DL_FRAME_PARMS *frame_parms, + NR_UE_PDCCH *pdcch_vars, + NR_UE_PDSCH *pdsch_vars, + uint8_t nr_tti_rx, + uint16_t rnti, + uint16_t tc_rnti, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + NR_DL_UE_HARQ_t *pdlsch0_harq, + NR_UE_DLSCH_t *pdlsch0) +{ + + uint8_t harq_pid = pdci_info_extarcted->harq_pid; + uint8_t vrb_type = pdci_info_extarcted->vrb_type; + uint32_t rballoc = pdci_info_extarcted->rballoc; + uint8_t mcs1 = pdci_info_extarcted->mcs1; + uint8_t rv1 = pdci_info_extarcted->rv1; + uint8_t ndi1 = pdci_info_extarcted->ndi1; + uint8_t TPC = pdci_info_extarcted->TPC; + uint8_t rah = pdci_info_extarcted->rah; + uint8_t dai = pdci_info_extarcted->dai; + + uint8_t NPRB = 0; + uint8_t nb_rb_alloc = 0; + + if(dci_format == format1A) + { + if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) + { + NPRB = (TPC&1) + 2; + switch (N_RB_DL) { + case 6: + nb_rb_alloc = RIV2nb_rb_LUT6[rballoc];//NPRB; + break; + case 25: + nb_rb_alloc = RIV2nb_rb_LUT25[rballoc];//NPRB; + break; + case 50: + nb_rb_alloc = RIV2nb_rb_LUT50[rballoc];//NPRB; + break; + case 100: + nb_rb_alloc = RIV2nb_rb_LUT100[rballoc];//NPRB; + break; + } + } + else + { + switch (N_RB_DL) { + case 6: + NPRB = RIV2nb_rb_LUT6[rballoc];//NPRB; + break; + case 25: + NPRB = RIV2nb_rb_LUT25[rballoc];//NPRB; + break; + case 50: + NPRB = RIV2nb_rb_LUT50[rballoc];//NPRB; + break; + case 100: + NPRB = RIV2nb_rb_LUT100[rballoc];//NPRB; + break; + } + nb_rb_alloc = NPRB; + } + } + else // format1 + { + NPRB = conv_nprb(rah, rballoc, N_RB_DL); + nb_rb_alloc = NPRB; + } + + pdlsch0->current_harq_pid = harq_pid; + pdlsch0->active = 1; + pdlsch0->rnti = rnti; + if(dci_format == format1A) + pdlsch0->harq_ack[nr_tti_rx].vDAI_DL = dai+1; + + if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) + { + pdlsch0_harq->round = 0; + pdlsch0_harq->status = ACTIVE; + } + else //CRNTI + { + if (rnti == tc_rnti) { + //fix for standalone Contention Resolution Id + pdlsch0_harq->DCINdi = (uint8_t)-1; + LOG_D(PHY,"UE (%x/%d): Format1A DCI: C-RNTI is temporary. Set NDI = %d and to be ignored\n", + rnti,harq_pid,pdlsch0_harq->DCINdi); + } + + // NDI has been toggled or this is the first transmission + if ((ndi1!=pdlsch0_harq->DCINdi) || (pdlsch0_harq->first_tx==1)) + { + pdlsch0_harq->round = 0; + pdlsch0_harq->first_tx = 0; + pdlsch0_harq->status = ACTIVE; + + }else if (rv1 != 0 ) + //NDI has not been toggled but rv was increased by eNB: retransmission + { + if (pdlsch0_harq->status == SCH_IDLE) + //packet was actually decoded in previous transmission (ACK was missed by eNB) + //However, the round is not a good check as it might have been decoded in a retransmission prior to this one. + { + LOG_D(PHY,"skip pdsch decoding and report ack\n"); + // skip pdsch decoding and report ack + //pdlsch0_harq->status = SCH_IDLE; + pdlsch0->active = 0; + pdlsch0->harq_ack[nr_tti_rx].ack = 1; + pdlsch0->harq_ack[nr_tti_rx].harq_id = harq_pid; + pdlsch0->harq_ack[nr_tti_rx].send_harq_status = 1; + + //pdlsch0_harq->first_tx = 0; + } + else //normal retransmission + { + // nothing special to do + } + } + else + { + pdlsch0_harq->status = ACTIVE; + } + } + + pdlsch0_harq->DCINdi = ndi1; + pdlsch0_harq->mcs = mcs1; + pdlsch0_harq->rvidx = rv1; + pdlsch0_harq->nb_rb = NPRB; + + pdlsch0_harq->codeword = 0; + pdlsch0_harq->Nl = 1; + pdlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI; + pdlsch0_harq->dl_power_off = 1; //no power offset + pdlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC &3]; + + // compute resource allocation + if(dci_format == format1A) + { + switch (N_RB_DL) { + case 6: + if (vrb_type == LOCALIZED) { + pdlsch0_harq->rb_alloc_even[0] = localRIV2alloc_LUT6[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = localRIV2alloc_LUT6[rballoc]; + } + else { + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_even_LUT6[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_odd_LUT6[rballoc]; + } + break; + + case 25: + if (vrb_type == LOCALIZED) { + pdlsch0_harq->rb_alloc_even[0] = localRIV2alloc_LUT25[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = localRIV2alloc_LUT25[rballoc]; + } + else { + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_even_LUT25[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_odd_LUT25[rballoc]; + } + break; + + case 50: + if (vrb_type == LOCALIZED) { + pdlsch0_harq->rb_alloc_even[0] = localRIV2alloc_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = localRIV2alloc_LUT50_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = localRIV2alloc_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = localRIV2alloc_LUT50_1[rballoc]; + // printf("rballoc: %08x.%08x\n",pdlsch0_harq->rb_alloc_even[0],pdlsch0_harq->rb_alloc_even[1]); + } else { // DISTRIBUTED + if ((rballoc&(1<<10)) == 0) { + rballoc = rballoc&(~(1<<10)); + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT50_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT50_1[rballoc]; + } + else { + rballoc = rballoc&(~(1<<10)); + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT50_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT50_1[rballoc]; + } + } + break; + + case 100: + if (vrb_type == LOCALIZED) { + pdlsch0_harq->rb_alloc_even[0] = localRIV2alloc_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = localRIV2alloc_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_even[2] = localRIV2alloc_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_even[3] = localRIV2alloc_LUT100_3[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = localRIV2alloc_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = localRIV2alloc_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[2] = localRIV2alloc_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_odd[3] = localRIV2alloc_LUT100_3[rballoc]; + } else { + if ((rballoc&(1<<10)) == 0) { //Gap 1 + rballoc = rballoc&(~(1<<12)); + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_even[2] = distRIV2alloc_gap0_even_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_even[3] = distRIV2alloc_gap0_even_LUT100_3[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[2] = distRIV2alloc_gap0_odd_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_odd[3] = distRIV2alloc_gap0_odd_LUT100_3[rballoc]; + } + else { //Gap 2 + rballoc = rballoc&(~(1<<12)); + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap1_even_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap1_even_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_even[2] = distRIV2alloc_gap1_even_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_even[3] = distRIV2alloc_gap1_even_LUT100_3[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap1_odd_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap1_odd_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[2] = distRIV2alloc_gap1_odd_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_odd[3] = distRIV2alloc_gap1_odd_LUT100_3[rballoc]; + } + } + break; + } + } + else // format1 + { + conv_rballoc(rah,rballoc,frame_parms->N_RB_DL,pdlsch0_harq->rb_alloc_even); + pdlsch0_harq->rb_alloc_odd[0]= pdlsch0_harq->rb_alloc_even[0]; + pdlsch0_harq->rb_alloc_odd[1]= pdlsch0_harq->rb_alloc_even[1]; + pdlsch0_harq->rb_alloc_odd[2]= pdlsch0_harq->rb_alloc_even[2]; + pdlsch0_harq->rb_alloc_odd[3]= pdlsch0_harq->rb_alloc_even[3]; + } + if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) + { + pdlsch0_harq->TBS = TBStable[mcs1][NPRB-1]; + pdlsch0_harq->Qm = 2; + } + else + { + if(mcs1 < 29) + { + pdlsch0_harq->TBS = TBStable[get_I_TBS(mcs1)][NPRB-1]; + pdlsch0_harq->Qm = get_Qm(mcs1); + } + } + + compute_llr_offset(frame_parms, + pdcch_vars, + pdsch_vars, + pdlsch0_harq, + nb_rb_alloc, + nr_tti_rx); +} + +void prepare_dl_decoding_format1C(uint8_t N_RB_DL, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + NR_DL_FRAME_PARMS *frame_parms, + NR_UE_PDCCH *pdcch_vars, + NR_UE_PDSCH *pdsch_vars, + uint32_t rnti, + uint32_t si_rnti, + uint32_t ra_rnti, + uint32_t p_rnti, + uint32_t frame, + uint8_t nr_tti_rx, + NR_DL_UE_HARQ_t *pdlsch0_harq, + NR_UE_DLSCH_t *pdlsch0) +{ + + uint8_t harq_pid = pdci_info_extarcted->harq_pid; + uint32_t rballoc = pdci_info_extarcted->rballoc; + uint8_t mcs1 = pdci_info_extarcted->mcs1; + uint8_t Ngap = pdci_info_extarcted->Ngap; + + pdlsch0_harq->round = 0; + pdlsch0_harq->first_tx = 1; + pdlsch0_harq->vrb_type = DISTRIBUTED; + + if (rnti==si_rnti) { // rule from Section 5.3.1 of 36.321 + if (((frame&1) == 0) && (nr_tti_rx == 5)) + pdlsch0_harq->rvidx = (((3*((frame>>1)&3))+1)>>1)&3; // SIB1 + else + pdlsch0_harq->rvidx = (((3*(nr_tti_rx&3))+1)>>1)&3; // other SIBs + } + else if ((rnti==p_rnti) || (rnti==ra_rnti)) { // Section 7.1.7.3 + pdlsch0_harq->rvidx = 0; + } + + + pdlsch0_harq->Nl = 1; + pdlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI; + pdlsch0_harq->dl_power_off = 1; //no power offset + + pdlsch0_harq->codeword = 0; + pdlsch0_harq->mcs = mcs1; + pdlsch0_harq->TBS = TBStable1C[mcs1]; + pdlsch0_harq->Qm = 2; + + + pdlsch0->current_harq_pid = harq_pid; + pdlsch0->active = 1; + pdlsch0->rnti = rnti; + + switch (N_RB_DL) { + case 6: + pdlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rballoc]; + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_even_LUT6[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_odd_LUT6[rballoc]; + + break; + + case 25: + pdlsch0_harq->nb_rb = RIV2nb_rb_LUT25[rballoc]; + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_even_LUT25[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_odd_LUT25[rballoc]; + break; + + case 50: + pdlsch0_harq->nb_rb = RIV2nb_rb_LUT50[rballoc]; + if (Ngap == 0) { + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT50_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT50_1[rballoc]; + } + else { + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap1_even_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap1_odd_LUT50_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap1_even_LUT50_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap1_odd_LUT50_1[rballoc]; + } + break; + + case 100: + pdlsch0_harq->nb_rb = RIV2nb_rb_LUT100[rballoc]; + if (Ngap==0) { + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_even[2] = distRIV2alloc_gap0_even_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_odd[2] = distRIV2alloc_gap0_odd_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_even[3] = distRIV2alloc_gap0_even_LUT100_3[rballoc]; + pdlsch0_harq->rb_alloc_odd[3] = distRIV2alloc_gap0_odd_LUT100_3[rballoc]; + } + else { + pdlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap1_even_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap1_odd_LUT100_0[rballoc]; + pdlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap1_even_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap1_odd_LUT100_1[rballoc]; + pdlsch0_harq->rb_alloc_even[2] = distRIV2alloc_gap1_even_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_odd[2] = distRIV2alloc_gap1_odd_LUT100_2[rballoc]; + pdlsch0_harq->rb_alloc_even[3] = distRIV2alloc_gap1_even_LUT100_3[rballoc]; + pdlsch0_harq->rb_alloc_odd[3] = distRIV2alloc_gap1_odd_LUT100_3[rballoc]; + } + break; + + default: + AssertFatal(0,"Format 1C: Unknown N_RB_DL %d\n",frame_parms->N_RB_DL); + break; + } + + compute_llr_offset(frame_parms, + pdcch_vars, + pdsch_vars, + pdlsch0_harq, + pdlsch0_harq->nb_rb, + nr_tti_rx); + +} + +void compute_precoding_info_2cw(uint8_t tpmi, uint8_t tbswap, uint16_t pmi_alloc, NR_DL_FRAME_PARMS *frame_parms, NR_DL_UE_HARQ_t *dlsch0_harq, NR_DL_UE_HARQ_t *dlsch1_harq) +{ + +switch (tpmi) { + case 0: + dlsch0_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODING1; + dlsch1_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODING1; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,0, 1); + dlsch1_harq->pmi_alloc = pmi_extend(frame_parms,0, 1); + break; + case 1: + dlsch0_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODINGj; + dlsch1_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODINGj; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1, 1); + dlsch1_harq->pmi_alloc = pmi_extend(frame_parms,1, 1); + break; + case 2: // PUSCH precoding + dlsch0_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING; + dlsch1_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING; + if (tbswap==0){ + dlsch0_harq->pmi_alloc = pmi_alloc; + dlsch1_harq->pmi_alloc = pmi_alloc^0x1555; + } else { + dlsch1_harq->pmi_alloc = pmi_alloc; + dlsch0_harq->pmi_alloc = pmi_alloc^0x1555; + } +#ifdef DEBUG_HARQ + printf ("\n \n compute_precoding_info_2cw pmi_alloc_new = %d\n", dlsch0_harq->pmi_alloc); + #endif + break; + default: + break; + } +} + +void compute_precoding_info_1cw(uint8_t tpmi, uint16_t pmi_alloc, NR_DL_FRAME_PARMS *frame_parms, NR_DL_UE_HARQ_t *dlsch_harq) +{ + +switch (tpmi) { + case 0 : + dlsch_harq->mimo_mode = ALAMOUTI; + break; + case 1: + dlsch_harq->mimo_mode = UNIFORM_PRECODING11; + dlsch_harq->pmi_alloc = pmi_extend(frame_parms,0, 0); + break; + case 2: + dlsch_harq->mimo_mode = UNIFORM_PRECODING1m1; + dlsch_harq->pmi_alloc = pmi_extend(frame_parms,1, 0); + break; + case 3: + dlsch_harq->mimo_mode = UNIFORM_PRECODING1j; + dlsch_harq->pmi_alloc = pmi_extend(frame_parms,2, 0); + break; + case 4: + dlsch_harq->mimo_mode = UNIFORM_PRECODING1mj; + dlsch_harq->pmi_alloc = pmi_extend(frame_parms,3, 0); + break; + case 5: + dlsch_harq->mimo_mode = PUSCH_PRECODING0; + dlsch_harq->pmi_alloc = pmi_alloc;//pmi_convert(frame_parms,dlsch0->pmi_alloc,0); + break; + case 6: + dlsch_harq->mimo_mode = PUSCH_PRECODING1; + dlsch_harq->pmi_alloc = pmi_alloc;//pmi_convert(frame_parms,dlsch0->pmi_alloc,1); + break; + } + #ifdef DEBUG_HARQ + printf ("[DCI UE] I am calling from the UE side pmi_alloc_new = %d with tpmi %d\n", dlsch_harq->pmi_alloc, tpmi); + #endif + } + +void compute_precoding_info_format2A(uint8_t tpmi, + uint8_t nb_antenna_ports_eNB, + uint8_t tb0_active, + uint8_t tb1_active, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq) +{ + + dlsch0_harq->dl_power_off = 0; + dlsch1_harq->dl_power_off = 0; + + if (nb_antenna_ports_eNB == 2) { + if ((tb0_active==1) && (tb1_active==1)) { + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + } else { + dlsch0_harq->mimo_mode = ALAMOUTI; + dlsch1_harq->mimo_mode = ALAMOUTI; + } + } else if (nb_antenna_ports_eNB == 4) { // 4 antenna case + if ((tb0_active==1) && (tb1_active==1)) { + switch (tpmi) { + case 0: // one layer per transport block + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + break; + + case 1: // one-layers on TB 0, two on TB 1 + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->Nl = 2; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + break; + + case 2: // two-layers on TB 0, two on TB 1 + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch0_harq->Nl = 2; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + break; + + case 3: // + LOG_E(PHY,"Illegal value (3) for TPMI in Format 2A DCI\n"); + break; + } + } else if (tb0_active == 1) { + switch (tpmi) { + case 0: // one layer per transport block + dlsch0_harq->mimo_mode = ALAMOUTI; + dlsch1_harq->mimo_mode = ALAMOUTI; + break; + + case 1: // two-layers on TB 0 + dlsch0_harq->mimo_mode = LARGE_CDD; + dlsch0_harq->Nl = 2; + dlsch0_harq->dl_power_off = 1; + break; + + case 2: // two-layers on TB 0, two on TB 1 + case 3: // + LOG_E(PHY,"Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n",tpmi); + break; + } + } else if (tb1_active == 1) { + switch (tpmi) { + case 0: // one layer per transport block + dlsch0_harq->mimo_mode = ALAMOUTI; + dlsch1_harq->mimo_mode = ALAMOUTI; + break; + + case 1: // two-layers on TB 0 + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->Nl = 2; + dlsch0_harq->dl_power_off = 1; + break; + + case 2: // two-layers on TB 0, two on TB 1 + case 3: // + LOG_E(PHY,"Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n",tpmi); + break; + } + } + } + // printf("Format 2A: NPRB=%d (rballoc %x,mcs1 %d, mcs2 %d, frame_type %d N_RB_DL %d,active %d/%d)\n",NPRB,rballoc,mcs1,mcs2,frame_parms->frame_type,frame_parms->N_RB_DL,dlsch0->active,dlsch1->active); + //printf("UE (%x/%d): nr_tti_rx %d Format2A DCI: ndi1 %d, old_ndi1 %d, ndi2 %d, old_ndi2 %d (first tx1 %d, first tx2 %d) harq_status1 %d, harq_status2 %d\n",dlsch0->rnti,harq_pid,nr_tti_rx,ndi,dlsch0_harq->DCINdi, + // dlsch0_harq->first_tx,dlsch1_harq->first_tx,dlsch0_harq->status,dlsch1_harq->status); + //printf("TBS0 %d, TBS1 %d\n",dlsch0_harq->TBS,dlsch1_harq->TBS); + +} + +void prepare_dl_decoding_format2_2A(DCI_format_t dci_format, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + NR_DL_FRAME_PARMS *frame_parms, + NR_UE_PDCCH *pdcch_vars, + NR_UE_PDSCH *pdsch_vars, + uint16_t rnti, + uint8_t nr_tti_rx, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq, + NR_UE_DLSCH_t *pdlsch0, + NR_UE_DLSCH_t *pdlsch1) +{ + + uint8_t rah = pdci_info_extarcted->rah; + uint8_t mcs1 = pdci_info_extarcted->mcs1; + uint8_t mcs2 = pdci_info_extarcted->mcs2; + uint8_t rv1 = pdci_info_extarcted->rv1; + uint8_t rv2 = pdci_info_extarcted->rv2; + uint8_t harq_pid = pdci_info_extarcted->harq_pid; + uint32_t rballoc = pdci_info_extarcted->rballoc; + uint8_t tbswap = pdci_info_extarcted->tb_swap; + uint8_t tpmi = pdci_info_extarcted->tpmi; + uint8_t TPC = pdci_info_extarcted->TPC; + uint8_t ndi1 = pdci_info_extarcted->ndi1; + uint8_t ndi2 = pdci_info_extarcted->ndi2; + + uint8_t TB0_active = 1; + uint8_t TB1_active = 1; + + // printf("inside prepare pdlsch1->pmi_alloc %d \n",pdlsch1->pmi_alloc); + + + if ((rv1 == 1) && (mcs1 == 0)) { + TB0_active=0; + } + if ((rv2 == 1) && (mcs2 == 0)) { + TB1_active=0; + } + +#ifdef DEBUG_HARQ + printf("[DCI UE]: TB0 status %d , TB1 status %d\n", TB0_active, TB1_active); +#endif + + dlsch0_harq->mcs = mcs1; + dlsch1_harq->mcs = mcs2; + dlsch0_harq->rvidx = rv1; + dlsch1_harq->rvidx = rv2; + dlsch0_harq->DCINdi = ndi1; + dlsch1_harq->DCINdi = ndi2; + + dlsch0_harq->codeword = 0; + dlsch1_harq->codeword = 1; + dlsch0_harq->Nl = 1; + dlsch1_harq->Nl = 1; + dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; + dlsch1_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; + dlsch0_harq->dl_power_off = 1; + dlsch1_harq->dl_power_off = 1; + + pdlsch0->current_harq_pid = harq_pid; + pdlsch0->harq_ack[nr_tti_rx].harq_id = harq_pid; + pdlsch1->current_harq_pid = harq_pid; + pdlsch1->harq_ack[nr_tti_rx].harq_id = harq_pid; + + // assume two CW are active + dlsch0_harq->status = ACTIVE; + dlsch1_harq->status = ACTIVE; + pdlsch0->active = 1; + pdlsch1->active = 1; + pdlsch0->rnti = rnti; + pdlsch1->rnti = rnti; + + + if (TB0_active && TB1_active && tbswap==1) { + dlsch0_harq->codeword = 1; + dlsch1_harq->codeword = 0; + } + + + if (!TB0_active && TB1_active){ + dlsch1_harq->codeword = 0; + } + + if (TB0_active && !TB1_active){ + dlsch0_harq->codeword = 0; + } + + + if (TB0_active==0) { + dlsch0_harq->status = SCH_IDLE; + pdlsch0->active = 0; + #ifdef DEBUG_HARQ + printf("[DCI UE]: TB0 is deactivated, retransmit TB1 transmit in TM6\n"); + #endif + } + + if (TB1_active==0) { + dlsch1_harq->status = SCH_IDLE; + pdlsch1->active = 0; + } + +#ifdef DEBUG_HARQ + printf("[DCI UE]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status); +#endif + + // compute resource allocation + if (TB0_active == 1){ + + dlsch0_harq->nb_rb = conv_nprb(rah, + rballoc, + frame_parms->N_RB_DL); + conv_rballoc(rah, + rballoc, + frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc_even); + + dlsch0_harq->rb_alloc_odd[0]= dlsch0_harq->rb_alloc_even[0]; + dlsch0_harq->rb_alloc_odd[1]= dlsch0_harq->rb_alloc_even[1]; + dlsch0_harq->rb_alloc_odd[2]= dlsch0_harq->rb_alloc_even[2]; + dlsch0_harq->rb_alloc_odd[3]= dlsch0_harq->rb_alloc_even[3]; + + if (TB1_active == 1){ + dlsch1_harq->rb_alloc_even[0]= dlsch0_harq->rb_alloc_even[0]; + dlsch1_harq->rb_alloc_even[1]= dlsch0_harq->rb_alloc_even[1]; + dlsch1_harq->rb_alloc_even[2]= dlsch0_harq->rb_alloc_even[2]; + dlsch1_harq->rb_alloc_even[3]= dlsch0_harq->rb_alloc_even[3]; + dlsch1_harq->rb_alloc_odd[0] = dlsch0_harq->rb_alloc_odd[0]; + dlsch1_harq->rb_alloc_odd[1] = dlsch0_harq->rb_alloc_odd[1]; + dlsch1_harq->rb_alloc_odd[2] = dlsch0_harq->rb_alloc_odd[2]; + dlsch1_harq->rb_alloc_odd[3] = dlsch0_harq->rb_alloc_odd[3]; + + dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; + + //dlsch0_harq->Nl = 1; + //dlsch1_harq->Nl = 1; + } + } else if ((TB0_active == 0) && (TB1_active == 1)){ + + conv_rballoc(rah, + rballoc, + frame_parms->N_RB_DL, + dlsch1_harq->rb_alloc_even); + + dlsch1_harq->rb_alloc_odd[0]= dlsch1_harq->rb_alloc_even[0]; + dlsch1_harq->rb_alloc_odd[1]= dlsch1_harq->rb_alloc_even[1]; + dlsch1_harq->rb_alloc_odd[2]= dlsch1_harq->rb_alloc_even[2]; + dlsch1_harq->rb_alloc_odd[3]= dlsch1_harq->rb_alloc_even[3]; + dlsch1_harq->nb_rb = conv_nprb(rah, + rballoc, + frame_parms->N_RB_DL); + } + + + // compute precoding matrix + mimo mode + if(dci_format == format2) + { + if ((TB0_active) && (TB1_active)){ //two CW active + compute_precoding_info_2cw(tpmi, tbswap, pdlsch0->pmi_alloc,frame_parms, dlsch0_harq, dlsch1_harq); + + // printf("[DCI UE 1]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status); + } else if ((TB0_active) && (!TB1_active)) { // only CW 0 active + compute_precoding_info_1cw(tpmi, pdlsch0->pmi_alloc, frame_parms, dlsch0_harq); + } else { + compute_precoding_info_1cw(tpmi, pdlsch1->pmi_alloc, frame_parms, dlsch1_harq); + // printf("I am doing compute_precoding_info_1cw with tpmi %d \n", tpmi); + } + //printf(" UE DCI harq0 MIMO mode = %d\n", dlsch0_harq->mimo_mode); + if ((frame_parms->mode1_flag == 1) && (TB0_active)) + dlsch0_harq->mimo_mode = SISO; + } + else + { + compute_precoding_info_format2A( tpmi, + frame_parms->nb_antenna_ports_eNB, + TB0_active, + TB1_active, + dlsch0_harq, + dlsch1_harq); + } + // printf("[DCI UE 2]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status); + // reset round + compute Qm + if (TB0_active) { + // printf("TB0 ndi1 =%d, dlsch0_harq->DCINdi =%d, dlsch0_harq->first_tx = %d\n", ndi1, dlsch0_harq->DCINdi, dlsch0_harq->first_tx); + if ((ndi1!=dlsch0_harq->DCINdi) || (dlsch0_harq->first_tx==1)) { + dlsch0_harq->round = 0; + dlsch0_harq->status = ACTIVE; + dlsch0_harq->DCINdi = ndi1; + + //LOG_I(PHY,"[UE] DLSCH: New Data Indicator CW0 subframe %d (pid %d, round %d)\n", + // subframe,harq_pid,dlsch0_harq->round); + if ( dlsch0_harq->first_tx==1) { + LOG_D(PHY,"Format 2 DCI First TX0: Clearing flag\n"); + dlsch0_harq->first_tx = 0; + } + } + /*else if (rv1 != 0 ) + //NDI has not been toggled but rv was increased by eNB: retransmission + { + if(dlsch0_harq->status == SCH_IDLE) { + // skip pdsch decoding and report ack + //dlsch0_harq->status = SCH_IDLE; + pdlsch0->active = 0; + pdlsch0->harq_ack[subframe].ack = 1; + pdlsch0->harq_ack[subframe].harq_id = harq_pid; + pdlsch0->harq_ack[subframe].send_harq_status = 1; + }*/ + + // if Imcs in [29..31] TBS is assumed to be as determined from DCI transported in the latest + // PDCCH for the same trasport block using Imcs in [0 .. 28] + if(dlsch0_harq->mcs <= 28) + { + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + LOG_D(PHY,"[UE] DLSCH: New TBS CW0 nr_tti_rx %d (pid %d, round %d) TBS %d \n", + nr_tti_rx,harq_pid,dlsch0_harq->round, dlsch0_harq->TBS); + } + else + { + LOG_D(PHY,"[UE] DLSCH: Keep the same TBS CW0 nr_tti_rx %d (pid %d, round %d) TBS %d \n", + nr_tti_rx,harq_pid,dlsch0_harq->round, dlsch0_harq->TBS); + } + //if(dlsch0_harq->Nl == 2) + //dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][(dlsch0_harq->nb_rb<<1)-1]; + if (mcs1 <= 28) + dlsch0_harq->Qm = get_Qm(mcs1); + else if (mcs1<=31) + dlsch0_harq->Qm = (mcs1-28)<<1; + } + + // printf("[DCI UE 3]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status); + + if (TB1_active) { + // printf("TB1 ndi2 =%d, dlsch1_harq->DCINdi =%d, dlsch1_harq->first_tx = %d\n", ndi2, dlsch1_harq->DCINdi, dlsch1_harq->first_tx); + if ((ndi2!=dlsch1_harq->DCINdi) || (dlsch1_harq->first_tx==1)) { + dlsch1_harq->round = 0; + dlsch1_harq->status = ACTIVE; + dlsch1_harq->DCINdi = ndi2; + //LOG_I(PHY,"[UE] DLSCH: New Data Indicator CW1 subframe %d (pid %d, round %d)\n", + // subframe,harq_pid,dlsch0_harq->round); + if (dlsch1_harq->first_tx==1) { + LOG_D(PHY,"Format 2 DCI First TX1: Clearing flag\n"); + dlsch1_harq->first_tx = 0; + } + } + /*else if (rv1 != 0 ) + //NDI has not been toggled but rv was increased by eNB: retransmission + { + if(dlsch1_harq->status == SCH_IDLE) { + // skip pdsch decoding and report ack + //dlsch1_harq->status = SCH_IDLE; + pdlsch1->active = 0; + pdlsch1->harq_ack[subframe].ack = 1; + pdlsch1->harq_ack[subframe].harq_id = harq_pid; + pdlsch1->harq_ack[subframe].send_harq_status = 1; + } + }*/ + + // if Imcs in [29..31] TBS is assumed to be as determined from DCI transported in the latest + // PDCCH for the same trasport block using Imcs in [0 .. 28] + if(dlsch1_harq->mcs <= 28) + { + dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch1_harq->nb_rb-1]; + LOG_D(PHY,"[UE] DLSCH: New TBS CW1 nr_tti_rx %d (pid %d, round %d) TBS %d \n", + nr_tti_rx,harq_pid,dlsch1_harq->round, dlsch1_harq->TBS); + } + else + { + LOG_D(PHY,"[UE] DLSCH: Keep the same TBS CW1 nr_tti_rx %d (pid %d, round %d) TBS %d \n", + nr_tti_rx,harq_pid,dlsch1_harq->round, dlsch1_harq->TBS); + } + if (mcs2 <= 28) + dlsch1_harq->Qm = get_Qm(mcs2); + else if (mcs1<=31) + dlsch1_harq->Qm = (mcs2-28)<<1; + } + + + compute_llr_offset(frame_parms, + pdcch_vars, + pdsch_vars, + dlsch0_harq, + dlsch0_harq->nb_rb, + nr_tti_rx); + + + /* #ifdef DEBUG_HARQ + printf("[DCI UE]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status); + printf("[DCI UE]: TB0_active %d , TB1_active %d\n", TB0_active, TB1_active); + if (dlsch0 != NULL && dlsch1 != NULL) + printf("[DCI UE] dlsch0_harq status = %d, dlsch1_harq status = %d\n", dlsch0_harq->status, dlsch1_harq->status); + else if (dlsch0 == NULL && dlsch1 != NULL) + printf("[DCI UE] dlsch0_harq NULL dlsch1_harq status = %d\n", dlsch1_harq->status); + else if (dlsch0 != NULL && dlsch1 == NULL) + printf("[DCI UE] dlsch1_harq NULL dlsch0_harq status = %d\n", dlsch0_harq->status); + #endif*/ +} +#endif //(0) + +#ifdef NR_PDCCH_DCI_TOOLS +int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue, + uint8_t eNB_id, + int frame, + uint8_t nr_tti_rx, + void *dci_pdu, + uint16_t rnti, + NR_DCI_format_t dci_format, + NR_UE_PDCCH *pdcch_vars, + NR_UE_PDSCH *pdsch_vars, + NR_UE_DLSCH_t **dlsch, + NR_UE_ULSCH_t *ulsch, + NR_DL_FRAME_PARMS *frame_parms, + PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint8_t beamforming_mode, + uint16_t tc_rnti, + uint8_t dci_length, + uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS], + uint16_t n_RB_ULBWP, + uint16_t n_RB_DLBWP) +{ + /* + * Note only format0_0 and format1_0 are implemented + */ + + uint8_t harq_pid=0; + uint8_t frame_type=frame_parms->frame_type; + uint8_t tpmi=0; + NR_UE_DLSCH_t *dlsch0=NULL,*dlsch1=NULL; + NR_DL_UE_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL; + NR_UE_ULSCH_t *ulsch0=NULL,*ulsch1=NULL; + NR_DCI_INFO_EXTRACTED_t nr_dci_info_extracted; + uint8_t status=0,left_shift=0; + uint64_t pdu_bitmap = 0xFFFFFFFFFFFFFFFF; + pdu_bitmap = (pdu_bitmap << (64 - dci_length)) >> (64 - dci_length); // this variable will help to remove the bits of other fields when left-switching + + dlsch0 = dlsch[0]; + dlsch0->active = 0; + if (dci_fields_sizes[HARQ_PROCESS_NUMBER] != 0) { // 25 HARQ_PROCESS_NUMBER (25 is the position in dci_fields_sizes array for field HARQ_PROCESS_NUMBER) + for (int i=0; i<=HARQ_PROCESS_NUMBER; i++) left_shift = left_shift + dci_fields_sizes[i]; + nr_dci_info_extracted.harq_process_number = (uint8_t)(((((*(uint64_t *)dci_pdu) << (left_shift - dci_fields_sizes[HARQ_PROCESS_NUMBER]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[HARQ_PROCESS_NUMBER])); + left_shift = 0; + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> nr_dci_info_extracted->harq_process_number=%x\n",nr_dci_info_extracted.harq_process_number); + #endif + } + dlsch0_harq = dlsch[0]->harq_processes[nr_dci_info_extracted.harq_process_number]; + ulsch0 = ulsch; +/* printf("nr_dci_info_extracted.harq_process_number = %d\n",nr_dci_info_extracted.harq_process_number); + printf("dlsch0 = %d\n",dlsch0); + printf("dlsch0_harq = %d\n",dlsch0_harq);*/ + + if (!dlsch[0]) return -1; + if (!ulsch) return -1; + + memset(&nr_dci_info_extracted,0,sizeof(nr_dci_info_extracted)); +// printf("we reach this point\n"); + switch (dci_format) { + + case format0_0: + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> Entering function nr_extract_dci_info(dci_format=%d) for PUSCH allocation\n",dci_format); + #endif + status = nr_extract_dci_info(ue, + eNB_id, + frame_type, + dci_length, + dci_pdu, + &nr_dci_info_extracted, + dci_fields_sizes, + dlsch0_harq, + dlsch0, + ulsch0, + dci_format, + nr_tti_rx, + rnti, + si_rnti, + p_rnti, + ra_rnti, + tc_rnti, + n_RB_ULBWP, + n_RB_DLBWP); + //status = check_dci_format1_1a_coherency(format1_1, frame_parms->N_RB_DL, rnti, tc_rnti, si_rnti, ra_rnti, p_rnti,frame,nr_tti_rx, &nr_dci_info_extracted, dlsch0_harq); + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + if(status == 0) + { + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> bad DCI %d !!! \n",dci_format); + return(-1); + } + #endif + break; + + case format0_1: + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> format %d not implemented yet\n",dci_format); + #endif + break; + + case format1_0: + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> Entering function nr_extract_dci_info(dci_format=%d)for PDSCH allocation\n",dci_format); + #endif + status = nr_extract_dci_info(ue, + eNB_id, + frame_type, + dci_length, + dci_pdu, + &nr_dci_info_extracted, + dci_fields_sizes, + dlsch0_harq, + dlsch0, + ulsch0, + dci_format, + nr_tti_rx, + rnti, + si_rnti, + p_rnti, + ra_rnti, + tc_rnti, + n_RB_ULBWP, + n_RB_DLBWP); + //status = check_dci_format1_1a_coherency(format1_1, frame_parms->N_RB_DL, rnti, tc_rnti, si_rnti, ra_rnti, p_rnti,frame,nr_tti_rx, &nr_dci_info_extracted, dlsch0_harq); + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + if(status == 0) + { + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> bad DCI %d !!! \n",dci_format); + return(-1); + } + #endif + break; + + case format1_1: + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> format %d not implemented yet\n",dci_format); + #endif + break; + + case format2_0: + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> format %d not implemented yet\n",dci_format); + #endif + break; + + case format2_1: + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> format %d not implemented yet\n",dci_format); + #endif + break; + + case format2_2: + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> format %d not implemented yet\n",dci_format); + #endif + break; + + case format2_3: + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> format %d not implemented yet\n",dci_format); + #endif + break; + + default: + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> we go to the default in switch\n"); + //LOG_E(PHY,"format %d not yet implemented\n",dci_format); + return(-1); + break; + } + #ifdef NR_PDCCH_DCI_TOOLS_DEBUG + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> Ending function nr_extract_dci_info()\n"); + #endif + return(0); +} +#endif +#if 0 +int generate_ue_dlsch_params_from_dci(int frame, + uint8_t nr_tti_rx, + void *dci_pdu, + uint16_t rnti, + DCI_format_t dci_format, + NR_UE_PDCCH *pdcch_vars, + NR_UE_PDSCH *pdsch_vars, + NR_UE_DLSCH_t **dlsch, + NR_DL_FRAME_PARMS *frame_parms, + PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint8_t beamforming_mode, + uint16_t tc_rnti) +{ + + uint8_t harq_pid=0; + uint8_t frame_type=frame_parms->frame_type; + uint8_t tpmi=0; + NR_UE_DLSCH_t *dlsch0=NULL,*dlsch1=NULL; + NR_DL_UE_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL; + + DCI_INFO_EXTRACTED_t dci_info_extarcted; + uint8_t status=0; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + printf("####################### verifying pointer\n"); + dlsch0 = dlsch[0]; + dlsch0->active = 0; + dlsch0_harq = dlsch[0]->harq_processes[dci_info_extarcted.harq_pid]; + printf("####################### verifying pointer, dlsch0 = %p, dlsch0_harq = %p\n",dlsch0,dlsch0_harq); +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + if (!dlsch[0]) return -1; + + #ifdef DEBUG_DCI + LOG_D(PHY,"dci_tools.c: Filling ue dlsch params -> rnti %x, SFN/SF %d/%d, dci_format %s\n", + rnti, + frame%1024, + nr_tti_rx, + (dci_format==format0? "Format 0":( + dci_format==format1? "format 1":( + dci_format==format1A? "format 1A":( + dci_format==format1B? "format 1B":( + dci_format==format1C? "format 1C":( + dci_format==format1D? "format 1D":( + dci_format==format1E_2A_M10PRB? "format 1E_2A_M10PRB":( + dci_format==format2? "format 2":( + dci_format==format2A? "format 2A":( + dci_format==format2B? "format 2B":( + dci_format==format2C? "format 2C":( + dci_format==format2D? "format 2D":( + dci_format==format3? "format 3": "UNKNOWN" + )))))))))))))); + #endif + + memset(&dci_info_extarcted,0,sizeof(dci_info_extarcted)); + switch (dci_format) { + + case format0: // This is an ULSCH allocation so nothing here, inform MAC + LOG_E(PHY,"format0 not possible\n"); + return(-1); + break; + + case format1A: + { + // extract dci infomation +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1A] AbsSubframe %d.%d extarct dci info \n", frame, nr_tti_rx); +#endif + extract_dci1A_info(frame_parms->N_RB_DL, + frame_type, + dci_pdu, + &dci_info_extarcted); + + + // check dci content + dlsch0 = dlsch[0]; + dlsch0->active = 0; + dlsch0_harq = dlsch[0]->harq_processes[dci_info_extarcted.harq_pid]; +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1A] AbsSubframe %d.%d check dci coherency \n", frame, nr_tti_rx); +#endif + status = check_dci_format1_1a_coherency(format1A, + frame_parms->N_RB_DL, + rnti, + tc_rnti, + si_rnti, + ra_rnti, + p_rnti,frame,nr_tti_rx, + &dci_info_extarcted, + dlsch0_harq); + if(status == 0) + { + printf("bad DCI 1A !!! \n"); + return(-1); + } + + // dci is correct ==> update internal structure and prepare dl decoding +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1A] AbsSubframe %d.%d prepare dl decoding \n", frame, nr_tti_rx); +#endif + prepare_dl_decoding_format1_1A(format1A, + frame_parms->N_RB_DL, + &dci_info_extarcted, + frame_parms, + pdcch_vars, + pdsch_vars, + nr_tti_rx, + rnti, + tc_rnti, + si_rnti, + ra_rnti, + p_rnti, + dlsch0_harq, + dlsch0); + + + + break; + } + case format1C: + { + // extract dci infomation +#ifdef DEBUG_DL_DECODING + LOG_I(PHY,"[DCI Format-1C] extact dci information \n"); +#endif + extract_dci1C_info(frame_parms->N_RB_DL, + frame_type, + dci_pdu, + &dci_info_extarcted); + + + // check dci content +#ifdef DEBUG_DL_DECODING + LOG_I(PHY,"[DCI Format-1C] check dci content \n"); +#endif + dlsch0 = dlsch[0]; + dlsch0->active = 0; + dlsch0_harq = dlsch[0]->harq_processes[dci_info_extarcted.harq_pid]; + + status = check_dci_format1c_coherency(frame_parms->N_RB_DL, + &dci_info_extarcted, + rnti, + si_rnti, + ra_rnti, + p_rnti, + dlsch0_harq); + if(status == 0) + return(-1); + + // dci is correct ==> update internal structure and prepare dl decoding +#ifdef DEBUG_DL_DECODING + LOG_I(PHY,"[DCI Format-1C] prepare downlink decoding \n"); +#endif + prepare_dl_decoding_format1C(frame_parms->N_RB_DL, + &dci_info_extarcted, + frame_parms, + pdcch_vars, + pdsch_vars, + rnti, + si_rnti, + ra_rnti, + p_rnti, + frame, + nr_tti_rx, + dlsch0_harq, + dlsch0); + + break; + } + + case format1: + { + // extract dci infomation +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1] AbsSubframe %d.%d extarct dci info \n", frame, nr_tti_rx); +#endif + extract_dci1_info(frame_parms->N_RB_DL, + frame_type, + dci_pdu, + &dci_info_extarcted); + + // check dci content + dlsch0 = dlsch[0]; + dlsch0->active = 0; + dlsch0_harq = dlsch[0]->harq_processes[dci_info_extarcted.harq_pid]; + +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1] AbsSubframe %d.%d check dci coherency \n", frame, nr_tti_rx); +#endif + status = check_dci_format1_1a_coherency(format1, + frame_parms->N_RB_DL, + rnti, + tc_rnti, + si_rnti, + ra_rnti, + p_rnti,frame,nr_tti_rx, + &dci_info_extarcted, + dlsch0_harq); + if(status == 0) + { + printf("bad DCI 1 !!! \n"); + return(-1); + } + + + // dci is correct ==> update internal structure and prepare dl decoding +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1] AbsSubframe %d.%d prepare dl decoding \n", frame, nr_tti_rx); +#endif + prepare_dl_decoding_format1_1A(format1, + frame_parms->N_RB_DL, + &dci_info_extarcted, + frame_parms, + pdcch_vars, + pdsch_vars, + nr_tti_rx, + rnti, + tc_rnti, + si_rnti, + ra_rnti, + p_rnti, + dlsch0_harq, + dlsch0); + break; + } + + case format2: + { + // extract dci infomation + //LOG_I(PHY,"[DCI-format2] AbsSubframe %d.%d extract dci infomation \n", frame, subframe); + extract_dci2_info(frame_parms->N_RB_DL, + frame_type, + frame_parms->nb_antenna_ports_eNB, + dci_pdu, + &dci_info_extarcted); + + + // check dci content + dlsch[0]->active = 1; + dlsch[1]->active = 1; + + dlsch0 = dlsch[0]; + dlsch1 = dlsch[1]; + + dlsch0_harq = dlsch0->harq_processes[dci_info_extarcted.harq_pid]; + dlsch1_harq = dlsch1->harq_processes[dci_info_extarcted.harq_pid]; + // printf("before coherency dlsch[1]->pmi_alloc %d\n",dlsch[1]->pmi_alloc); + // printf("before coherency dlsch1->pmi_alloc %d\n",dlsch1->pmi_alloc); + // printf("before coherency dlsch1_harq->pmi_alloc %d\n",dlsch1_harq->pmi_alloc); + + //LOG_I(PHY,"[DCI-format2] check dci content \n"); + status = check_dci_format2_2a_coherency(format2, + frame_parms->N_RB_DL, + &dci_info_extarcted, + rnti, + si_rnti, + ra_rnti, + p_rnti, + dlsch0_harq, + dlsch1_harq); + if(status == 0) + return(-1); + + + // dci is correct ==> update internal structure and prepare dl decoding + //LOG_I(PHY,"[DCI-format2] update internal structure and prepare dl decoding \n"); + prepare_dl_decoding_format2_2A(format2, + &dci_info_extarcted, + frame_parms, + pdcch_vars, + pdsch_vars, + rnti, + nr_tti_rx, + dlsch0_harq, + dlsch1_harq, + dlsch0, + dlsch1); + } + break; + + case format2A: + { + // extract dci infomation + LOG_I(PHY,"[DCI-format2] AbsSubframe %d.%d extract dci infomation \n", frame%1024, nr_tti_rx); + extract_dci2A_info(frame_parms->N_RB_DL, + frame_type, + frame_parms->nb_antenna_ports_eNB, + dci_pdu, + &dci_info_extarcted); + + // check dci content + //LOG_I(PHY,"[DCI-format2A] check dci content \n"); + //LOG_I(PHY,"[DCI-format2A] tb_swap %d harq_pid %d\n", dci_info_extarcted.tb_swap, dci_info_extarcted.harq_pid); + //dlsch[0]->active = 0; + //dlsch[1]->active = 0; + + if (dci_info_extarcted.tb_swap == 0) { + dlsch0 = dlsch[0]; + dlsch1 = dlsch[1]; + } else { + dlsch0 = dlsch[1]; + dlsch1 = dlsch[0]; + } + dlsch0_harq = dlsch0->harq_processes[dci_info_extarcted.harq_pid]; + dlsch1_harq = dlsch1->harq_processes[dci_info_extarcted.harq_pid]; + + //LOG_I(PHY,"[DCI-format2A] check dci content \n"); + status = check_dci_format2_2a_coherency(format2A, + frame_parms->N_RB_DL, + &dci_info_extarcted, + rnti, + si_rnti, + ra_rnti, + p_rnti, + dlsch0_harq, + dlsch1_harq); + if(status == 0) + return(-1); + + // dci is correct ==> update internal structure and prepare dl decoding + //LOG_I(PHY,"[DCI-format2A] update internal structure and prepare dl decoding \n"); + prepare_dl_decoding_format2_2A(format2A, + &dci_info_extarcted, + frame_parms, + pdcch_vars, + pdsch_vars, + rnti, + nr_tti_rx, + dlsch0_harq, + dlsch1_harq, + dlsch0, + dlsch1); + } + break; + + case format1E_2A_M10PRB: + if (!dlsch[0]) return -1; + + harq_pid = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->harq_pid; + + if (harq_pid>=8) { + LOG_E(PHY,"Format 1E_2A_M10PRB: harq_pid=%d >= 8\n", harq_pid); + return(-1); + } + + dlsch[0]->current_harq_pid = harq_pid; + dlsch[0]->harq_ack[nr_tti_rx].harq_id = harq_pid; + + /* + tbswap = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tb_swap; + if (tbswap == 0) { + dlsch0 = dlsch[0]; + dlsch1 = dlsch[1]; + } + else{ + dlsch0 = dlsch[1]; + dlsch1 = dlsch[0]; + } + */ + dlsch0 = dlsch[0]; + + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + // Needs to be checked + dlsch0_harq->codeword=0; + conv_rballoc(((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rah, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rballoc,frame_parms->N_RB_DL, + dlsch0_harq->rb_alloc_even); + + dlsch0_harq->rb_alloc_odd[0] = dlsch0_harq->rb_alloc_even[0]; + dlsch0_harq->rb_alloc_odd[1] = dlsch0_harq->rb_alloc_even[1]; + dlsch0_harq->rb_alloc_odd[2] = dlsch0_harq->rb_alloc_even[2]; + dlsch0_harq->rb_alloc_odd[3] = dlsch0_harq->rb_alloc_even[3]; + /* + dlsch1_harq->rb_alloc_even[0] = dlsch0_harq->rb_alloc_even[0]; + dlsch1_harq->rb_alloc_even[1] = dlsch0_harq->rb_alloc_even[1]; + dlsch1_harq->rb_alloc_even[2] = dlsch0_harq->rb_alloc_even[2]; + dlsch1_harq->rb_alloc_even[3] = dlsch0_harq->rb_alloc_even[3]; + */ + dlsch0_harq->nb_rb = conv_nprb(((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rah, + ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rballoc, + frame_parms->N_RB_DL); + //dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; + + dlsch0_harq->mcs = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->mcs; + dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->TPC&3]; + + + + /* + if (dlsch0_harq->mcs>20) { + printf("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs); + return(-1); + } + */ + + //dlsch1_harq->mcs = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->mcs2; + dlsch0_harq->rvidx = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rv; + //dlsch1_harq->rvidx = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->rv2; + + // check if either TB is disabled (see 36-213 V8.6 p. 26) + + if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) { + dlsch0_harq->status = DISABLED; + } + + //if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) { + //dlsch1_harq->status = DISABLED; + //} + dlsch0_harq->Nl = 1; + + //dlsch0->layer_index = tbswap; + //dlsch1->layer_index = 1-tbswap; + + + // Fix this + tpmi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tpmi; + // printf("ue: tpmi %d\n",tpmi); + + switch (tpmi) { + case 0 : + dlsch0_harq->mimo_mode = ALAMOUTI; + break; + + case 1: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING11; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,0,0); + break; + + case 2: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1m1; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1, 0); + break; + + case 3: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1j; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,2, 0); + + break; + + case 4: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1mj; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,3, 0); + break; + + case 5: + dlsch0_harq->mimo_mode = PUSCH_PRECODING0; + // pmi stored from ulsch allocation routine + dlsch0_harq->pmi_alloc = dlsch0->pmi_alloc; + //LOG_I(PHY,"XXX using PMI %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc)); + break; + + case 6: + dlsch0_harq->mimo_mode = PUSCH_PRECODING1; + LOG_E(PHY,"Unsupported TPMI\n"); + return(-1); + break; + } + + + if (frame_parms->mode1_flag == 1) + dlsch0_harq->mimo_mode = SISO; + + + if ((dlsch0_harq->DCINdi != ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi) || + (dlsch0_harq->first_tx==1)) { + + dlsch0_harq->round = 0; + dlsch0_harq->first_tx = 0; + dlsch0_harq->status = ACTIVE; + } + /* + else if (dlsch0_harq->status == SCH_IDLE) { // we got same ndi for a previously decoded process, + // this happens if either another harq process in the same + // is NAK or an ACK was not received + + dlsch0->harq_ack[subframe].ack = 1; + dlsch0->harq_ack[subframe].harq_id = harq_pid; + dlsch0->harq_ack[subframe].send_harq_status = 1; + dlsch0->active = 0; + return(0); + } + */ + + dlsch0_harq->DCINdi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi; + dlsch0_harq->mcs = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->mcs; + + if (dlsch0_harq->nb_rb>1) { + dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; + } else + dlsch0_harq->TBS =0; + + dlsch0->rnti = rnti; + //dlsch1->rnti = rnti; + + dlsch0->active = 1; + //dlsch1->active = 1; + + dlsch0_harq->dl_power_off = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->dl_power_off; + //dlsch1_harq->dl_power_off = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->dl_power_off; + + + break; + + default: + LOG_E(PHY,"format %d not yet implemented\n",dci_format); + return(-1); + break; + } + +#ifdef UE_DEBUG_TRACE + + if (dlsch[0] && (dlsch[0]->rnti != 0xffff)) { + LOG_I(PHY,"dci_format:%d Abssubframe: %d.%d \n",dci_format,frame%1024,nr_tti_rx); + LOG_I(PHY,"PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); + LOG_D(PHY,"PDSCH dlsch0 UE: NBRB %d\n",dlsch0_harq->nb_rb); + LOG_D(PHY,"PDSCH dlsch0 UE: rballoc %x\n",dlsch0_harq->rb_alloc_even[0]); + LOG_I(PHY,"PDSCH dlsch0 UE: harq_pid %d\n",dci_info_extarcted.harq_pid); + LOG_I(PHY,"PDSCH dlsch0 UE: g %d\n",dlsch[0]->g_pucch); + LOG_D(PHY,"PDSCH dlsch0 UE: round %d\n",dlsch0_harq->round); + LOG_D(PHY,"PDSCH dlsch0 UE: DCINdi %d\n",dlsch0_harq->DCINdi); + LOG_D(PHY,"PDSCH dlsch0 UE: rvidx %d\n",dlsch0_harq->rvidx); + LOG_D(PHY,"PDSCH dlsch0 UE: TBS %d\n",dlsch0_harq->TBS); + LOG_D(PHY,"PDSCH dlsch0 UE: mcs %d\n",dlsch0_harq->mcs); + LOG_D(PHY,"PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); + } +#endif + + #if T_TRACER + if( (dlsch[0]->rnti != si_rnti) && (dlsch[0]->rnti != ra_rnti) && (dlsch[0]->rnti != p_rnti)) + { + T(T_UE_PHY_DLSCH_UE_DCI, T_INT(0), T_INT(frame%1024), T_INT(nr_tti_rx), T_INT(0), + T_INT(dlsch[0]->rnti), T_INT(dci_format), + T_INT(harq_pid), + T_INT(dlsch0_harq->mcs), + T_INT(dlsch0_harq->TBS)); + } + #endif + + + // compute DL power control parameters + if (dlsch0_harq != NULL){ + computeRhoA_UE(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off, frame_parms->nb_antenna_ports_eNB); + computeRhoB_UE(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[0],dlsch0_harq->dl_power_off); + } + + if (dlsch1_harq != NULL) { + computeRhoA_UE(pdsch_config_dedicated, dlsch[1],dlsch1_harq->dl_power_off, frame_parms->nb_antenna_ports_eNB); + computeRhoB_UE(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[1],dlsch1_harq->dl_power_off); + } + + + return(0); +} + +#endif //(0) +uint8_t nr_subframe2harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t nr_tti_rx) +{ + /* + #ifdef DEBUG_DCI + if (frame_parms->frame_type == TDD) + printf("dci_tools.c: subframe2_harq_pid, subframe %d for TDD configuration %d\n",subframe,frame_parms->tdd_config); + else + printf("dci_tools.c: subframe2_harq_pid, subframe %d for FDD \n",subframe); + #endif + */ + + uint8_t ret = 255; + uint8_t subframe = nr_tti_rx>>((int)(log2 (frame_parms->ttis_per_subframe))); + + if (frame_parms->frame_type == FDD) { + ret = (((frame<<1)+nr_tti_rx)&7); + } else { + + switch (frame_parms->tdd_config) { + + case 1: + if ((subframe==2) || + (subframe==3) || + (subframe==7) || + (subframe==8)) + switch (subframe) { + case 2: + case 3: + ret = (subframe-2); + break; + + case 7: + case 8: + ret = (subframe-5); + break; + + default: + LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config); + ret = (255); + break; + } + + break; + + case 2: + if ((subframe!=2) && (subframe!=7)) { + LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config); + //mac_xface->macphy_exit("subframe2_harq_pid, Illegal subframe"); + ret = (255); + } + + ret = (subframe/7); + break; + + case 3: + if ((subframe<2) || (subframe>4)) { + LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config); + ret = (255); + } + + ret = (subframe-2); + break; + + case 4: + if ((subframe<2) || (subframe>3)) { + LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config); + ret = (255); + } + + ret = (subframe-2); + break; + + case 5: + if (subframe!=2) { + LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config); + ret = (255); + } + + ret = (subframe-2); + break; + + default: + LOG_E(PHY,"subframe2_harq_pid, Unsupported TDD mode %d\n",frame_parms->tdd_config); + ret = (255); + + } + } + + if (ret == 255) { + LOG_E(PHY, "invalid harq_pid(%d) at SFN/SF = %d/%d\n", ret, frame, subframe); + //mac_xface->macphy_exit("invalid harq_pid"); + } + return ret; +} + + +uint8_t nr_pdcch_alloc2ul_subframe(NR_DL_FRAME_PARMS *frame_parms,uint8_t n) +{ + uint8_t ul_subframe = 255; + + if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 1) && + ((n==1)||(n==6))) // tdd_config 0,1 SF 1,5 + ul_subframe = ((n+6)%10); + else if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 6) && + ((n==0)||(n==1)||(n==5)||(n==6))) + ul_subframe = ((n+7)%10); + else if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 6) && + (n==9)) // tdd_config 6 SF 9 + ul_subframe = ((n+5)%10); + else + ul_subframe = ((n+4)%10); + + LOG_D(PHY, "subframe %d: PUSCH subframe = %d\n", n, ul_subframe); + return ul_subframe; +} +#if 0 +uint8_t ul_subframe2pdcch_alloc_subframe(NR_DL_FRAME_PARMS *frame_parms,uint8_t n) +{ + if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 1) && + ((n==7)||(n==2))) // tdd_config 0,1 SF 1,5 + return((n==7)? 1 : 6); + else if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 6) && + ((n==7)||(n==8)||(n==2)||(n==3))) + return((n+3)%10); + else if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 6) && + (n==4)) // tdd_config 6 SF 9 + return(9); + else + return((n+6)%10); + +} +#endif //(0) + +uint32_t nr_pdcch_alloc2ul_frame(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t n) +{ + uint32_t ul_frame = 255; + + if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 1) && + ((n==1)||(n==6))) // tdd_config 0,1 SF 1,5 + ul_frame = (frame + (n==1 ? 0 : 1)); + else if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 6) && + ((n==0)||(n==1)||(n==5)||(n==6))) + ul_frame = (frame + (n>=5 ? 1 : 0)); + else if ((frame_parms->frame_type == TDD) && + (frame_parms->tdd_config == 6) && + (n==9)) // tdd_config 6 SF 9 + ul_frame = (frame+1); + else + ul_frame = (frame+(n>=6 ? 1 : 0)); + + LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, n, ul_frame); + return ul_frame; + +} +#if 0 +int32_t pmi_convert_rank1_from_rank2(uint16_t pmi_alloc, int tpmi, int nb_rb) +{ + int nb_subbands = 0; + int32_t pmi_alloc_new = 0, pmi_new = 0, pmi_old = 0; + int i; + + switch (nb_rb) { + case 6: + nb_subbands = 6; + break; + default: + case 25: + nb_subbands = 7; + break; + case 50: + nb_subbands = 9; + break; + case 100: + nb_subbands = 13; + break; + } + + for (i = 0; i < nb_subbands; i++) { + pmi_old = (pmi_alloc >> i)&1; + + if (pmi_old == 0) + if (tpmi == 5) + pmi_new = 0; + else + pmi_new = 1; + else + if (tpmi == 5) + pmi_new = 2; + else + pmi_new = 3; + + pmi_alloc_new|=pmi_new<<(2*i); + + } +#ifdef DEBUG_HARQ +printf(" [DCI UE] pmi_alloc_old %d, pmi_alloc_new %d pmi_old %d , pmi_new %d\n", pmi_alloc, pmi_alloc_new,pmi_old, pmi_new ); +#endif +return(pmi_alloc_new); + +} + +uint16_t quantize_subband_pmi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,int nb_rb) +{ + + int i, aarx; + uint16_t pmiq=0; + uint32_t pmivect = 0; + uint8_t rank = meas->rank[eNB_id]; + int pmi_re,pmi_im; + int nb_subbands=0; + + + switch (nb_rb) { + case 6: + nb_subbands = 6; + break; + default: + case 25: + nb_subbands = 7; + break; + case 50: + nb_subbands = 9; + break; + case 100: + nb_subbands = 13; + break; + } + + + for (i=0; i<nb_subbands; i++) { + pmi_re = 0; + pmi_im = 0; + + if (rank == 0) { + for (aarx=0; aarx<meas->nb_antennas_rx; aarx++) { + pmi_re += meas->subband_pmi_re[eNB_id][i][aarx]; + pmi_im += meas->subband_pmi_im[eNB_id][i][aarx]; + } + + // pmi_re = meas->subband_pmi_re[eNB_id][i][meas->selected_rx_antennas[eNB_id][i]]; + // pmi_im = meas->subband_pmi_im[eNB_id][i][meas->selected_rx_antennas[eNB_id][i]]; + + // printf("pmi => (%d,%d)\n",pmi_re,pmi_im); + if ((pmi_re > pmi_im) && (pmi_re > -pmi_im)) + pmiq = PMI_2A_11; + else if ((pmi_re < pmi_im) && (pmi_re > -pmi_im)) + pmiq = PMI_2A_1j; + else if ((pmi_re < pmi_im) && (pmi_re < -pmi_im)) + pmiq = PMI_2A_1m1; + else if ((pmi_re > pmi_im) && (pmi_re < -pmi_im)) + pmiq = PMI_2A_1mj; + + // printf("subband %d, pmi%d \n",i,pmiq); + pmivect |= (pmiq<<(2*i)); + } + + else if (rank==1) { + for (aarx=0; aarx<meas->nb_antennas_rx; aarx++) { + pmi_re += meas->subband_pmi_re[eNB_id][i][aarx]; + //printf("meas->subband_pmi_re[eNB_id][i][%d]=%d\n", aarx, meas->subband_pmi_re[eNB_id][i][aarx]); + pmi_im += meas->subband_pmi_im[eNB_id][i][aarx]; + //printf("meas->subband_pmi_im[eNB_id][i][%d]=%d\n",aarx, meas->subband_pmi_im[eNB_id][i][aarx]); + } + if (pmi_re >= pmi_im) // this is not orthogonal + // this is orthogonal + //if (((pmi_re >= pmi_im) && (pmi_re >= -pmi_im)) || ((pmi_re <= pmi_im) && (pmi_re >= -pmi_im))) + pmiq = PMI_2A_R1_11; + else + pmiq = PMI_2A_R1_1j; + + // printf("subband %d, pmi_re %d, pmi_im %d, pmiq %d \n",i,pmi_re,pmi_im,pmiq); + // printf("subband %d, pmi%d \n",i,pmiq); + //According to Section 7.2.4 of 36.213 + + pmivect |= ((pmiq-1)<<(i)); //shift 1 since only one bit + } + else { + LOG_E(PHY,"PMI feedback for rank>1 not supported!\n"); + pmivect = 0; + } + + } +#ifdef DEBUG_HARQ + printf( "quantize_subband_pmi pmivect %d \n", pmivect); +#endif + return(pmivect); +} + +uint16_t quantize_subband_pmi2(PHY_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t a_id,int nb_subbands) +{ + + uint8_t i; + uint16_t pmiq=0; + uint16_t pmivect = 0; + uint8_t rank = meas->rank[eNB_id]; + int pmi_re,pmi_im; + + for (i=0; i<nb_subbands; i++) { + + if (rank == 0) { + pmi_re = meas->subband_pmi_re[eNB_id][i][a_id]; + pmi_im = meas->subband_pmi_im[eNB_id][i][a_id]; + + if ((pmi_re > pmi_im) && (pmi_re > -pmi_im)) + pmiq = PMI_2A_11; + else if ((pmi_re < pmi_im) && (pmi_re > -pmi_im)) + pmiq = PMI_2A_1j; + else if ((pmi_re < pmi_im) && (pmi_re < -pmi_im)) + pmiq = PMI_2A_1m1; + else if ((pmi_re > pmi_im) && (pmi_re < -pmi_im)) + pmiq = PMI_2A_1mj; + + pmivect |= (pmiq<<(2*i)); + } else { + // This needs to be done properly!!! + pmivect = 0; + } + } + + return(pmivect); +} + +uint16_t quantize_wideband_pmi(PHY_MEASUREMENTS *meas,uint8_t eNB_id) +{ + + uint16_t pmiq=0; + uint8_t rank = meas->rank[eNB_id]; + //int pmi; + int pmi_re,pmi_im; + + if (rank == 1) { + //pmi = + pmi_re = meas->wideband_pmi_re[eNB_id][meas->selected_rx_antennas[eNB_id][0]]; + pmi_im = meas->wideband_pmi_im[eNB_id][meas->selected_rx_antennas[eNB_id][0]]; + + if ((pmi_re > pmi_im) && (pmi_re > -pmi_im)) + pmiq = PMI_2A_11; + else if ((pmi_re < pmi_im) && (pmi_re > -pmi_im)) + pmiq = PMI_2A_1j; + else if ((pmi_re < pmi_im) && (pmi_re < -pmi_im)) + pmiq = PMI_2A_1m1; + else if ((pmi_re > pmi_im) && (pmi_re < -pmi_im)) + pmiq = PMI_2A_1mj; + + } else { + // This needs to be done properly! + pmiq = PMI_2A_11; + } + + + return(pmiq); +} +/* + uint8_t sinr2cqi(int sinr) { + if (sinr<-3) + return(0); + if (sinr>14) + return(10); + else + return(3+(sinr>>1)); + } +*/ + +uint8_t sinr2cqi(double sinr,uint8_t trans_mode) +{ + // int flag_LA=0; + + uint8_t retValue = 0; + + if(flag_LA==0) { + // Ideal Channel Estimation + if (sinr<=-4.89) + retValue = (0); + else if (sinr < -3.53) + retValue = (3); + else if (sinr <= -1.93) + retValue = (4); + else if (sinr <= -0.43) + retValue = (5); + else if (sinr <= 1.11) + retValue = (6); + else if (sinr <= 3.26) + retValue = (7); + else if (sinr <= 5.0) + retValue = (8); + else if (sinr <= 7.0) + retValue = (9); + else if (sinr <= 9.0) + retValue = (10); + else if (sinr <= 11.0) + retValue = (11); + else if (sinr <= 13.0) + retValue = (12); + else if (sinr <= 15.5) + retValue = (13); + else if (sinr <= 17.5) + retValue = (14); + else + retValue = (15); + } else { + int h=0; + int trans_mode_tmp; + + if (trans_mode ==5) + trans_mode_tmp=2; + else if(trans_mode ==6) + trans_mode_tmp=3; + else + trans_mode_tmp = trans_mode-1; + + for(h=0; h<16; h++) { + if(sinr<=sinr_to_cqi[trans_mode_tmp][h]) + retValue = (h); + } + } + + LOG_D(PHY, "sinr=%f trans_mode=%d cqi=%d\n", sinr, trans_mode, retValue); + return retValue; +} +//uint32_t fill_subband_cqi(PHY_MEASUREMENTS *meas,uint8_t eNB_id) { +// +// uint8_t i; +//// uint16_t cqivect = 0; +// uint32_t cqivect = 0; +// +//// char diff_cqi; +// int diff_cqi=0; +// +// for (i=0;i<NUMBER_OF_SUBBANDS;i++) { +// +// diff_cqi = -sinr2cqi(meas->wideband_cqi_dB[eNB_id][0]) + sinr2cqi(meas->subband_cqi_dB[eNB_id][0][i]); +// +// // Note, this is Table 7.2.1-2 from 36.213 +// if (diff_cqi<=-1) +// diff_cqi = 3; +// else if (diff_cqi>2) +// diff_cqi = 2; +// cqivect |= (diff_cqi<<(2*i)); +// +// } +// +// return(cqivect); +//} + + +uint32_t fill_subband_cqi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t trans_mode,int nb_subbands) +{ + + uint8_t i; + + uint32_t cqivect = 0,offset=0; + + + int diff_cqi=0; + + for (i=0; i<nb_subbands; i++) { + + diff_cqi = -sinr2cqi(meas->wideband_cqi_avg[eNB_id],trans_mode) + sinr2cqi(meas->subband_cqi_tot_dB[eNB_id][i],trans_mode); + + // Note, this is Table 7.2.1-2 from 36.213 + if (diff_cqi<=-1) + offset = 3; + else if (diff_cqi>=2) + offset = 2; + else + offset=(uint32_t)diff_cqi; + + cqivect |= (offset<<(2*i)); + + } + + return(cqivect); +} + +void fill_CQI(NR_UE_ULSCH_t *ulsch,PHY_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t harq_pid,int N_RB_DL,uint16_t rnti, uint8_t trans_mode, double sinr_eff) +{ + + // printf("[PHY][UE] Filling CQI for eNB %d, meas->wideband_cqi_tot[%d] %d\n", + // eNB_id,eNB_id,meas->wideband_cqi_tot[eNB_id]); + double sinr_tmp; + uint8_t *o = ulsch->o; + UCI_format_t uci_format = ulsch->uci_format; + + if(flag_LA==1) + sinr_tmp = sinr_eff; + else + sinr_tmp = (double) meas->wideband_cqi_avg[eNB_id]; + + + + //LOG_I(PHY,"[UE][UCI] Filling CQI format %d for eNB %d N_RB_DL %d\n",uci_format,eNB_id,N_RB_DL); + + switch (N_RB_DL) { + + case 6: + switch (uci_format) { + case wideband_cqi_rank1_2A: + ((wideband_cqi_rank1_2A_1_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((wideband_cqi_rank1_2A_1_5MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,6); + break; + + case wideband_cqi_rank2_2A: + ((wideband_cqi_rank2_2A_1_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); //FIXME: calculate rank2 cqi + ((wideband_cqi_rank2_2A_1_5MHz *)o)->cqi2 = sinr2cqi(sinr_tmp,trans_mode); //FIXME: calculate rank2 cqi + ((wideband_cqi_rank2_2A_1_5MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,6); + break; + + case HLC_subband_cqi_nopmi: + ((HLC_subband_cqi_nopmi_1_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_nopmi_1_5MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,6); + break; + + case HLC_subband_cqi_rank1_2A: + ((HLC_subband_cqi_rank1_2A_1_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank1_2A_1_5MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,6); + ((HLC_subband_cqi_rank1_2A_1_5MHz *)o)->pmi = quantize_wideband_pmi(meas,eNB_id); + break; + + case HLC_subband_cqi_rank2_2A: + // This has to be improved!!! + ((HLC_subband_cqi_rank2_2A_1_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank2_2A_1_5MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,6); + ((HLC_subband_cqi_rank2_2A_1_5MHz *)o)->cqi2 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank2_2A_1_5MHz *)o)->diffcqi2 = fill_subband_cqi(meas,eNB_id,trans_mode,6); + ((HLC_subband_cqi_rank2_2A_1_5MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,6); + break; + + case HLC_subband_cqi_mcs_CBA: + // this is the cba mcs uci for cba transmission + ((HLC_subband_cqi_mcs_CBA_1_5MHz *)o)->mcs = ulsch->harq_processes[harq_pid]->mcs; + ((HLC_subband_cqi_mcs_CBA_1_5MHz *)o)->crnti = rnti; + LOG_D(PHY,"fill uci for cba rnti %x, mcs %d \n", rnti, ulsch->harq_processes[harq_pid]->mcs); + break; + + case ue_selected: + LOG_E(PHY,"fill_CQI ue_selected CQI not supported yet!!!\n"); + mac_xface->macphy_exit("fill_CQI ue_selected CQI not supported yet!!!"); + break; + + default: + LOG_E(PHY,"unsupported CQI mode (%d)!!!\n",uci_format); + mac_xface->macphy_exit("unsupported CQI mode !!!"); + break; + + } + + break; + + case 25: + switch (uci_format) { + case wideband_cqi_rank1_2A: + ((wideband_cqi_rank1_2A_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((wideband_cqi_rank1_2A_5MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,7); + break; + + case wideband_cqi_rank2_2A: + ((wideband_cqi_rank2_2A_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); //FIXME: calculate rank2 cqi + ((wideband_cqi_rank2_2A_5MHz *)o)->cqi2 = sinr2cqi(sinr_tmp,trans_mode); //FIXME: calculate rank2 cqi + ((wideband_cqi_rank2_2A_5MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,7); + break; + + case HLC_subband_cqi_nopmi: + ((HLC_subband_cqi_nopmi_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_nopmi_5MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,7); + break; + + case HLC_subband_cqi_rank1_2A: + ((HLC_subband_cqi_rank1_2A_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank1_2A_5MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,7); + ((HLC_subband_cqi_rank1_2A_5MHz *)o)->pmi = quantize_wideband_pmi(meas,eNB_id); + break; + + case HLC_subband_cqi_rank2_2A: + // This has to be improved!!! + ((HLC_subband_cqi_rank2_2A_5MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank2_2A_5MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,7); + ((HLC_subband_cqi_rank2_2A_5MHz *)o)->cqi2 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank2_2A_5MHz *)o)->diffcqi2 = fill_subband_cqi(meas,eNB_id,trans_mode,7); + ((HLC_subband_cqi_rank2_2A_5MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,7); + break; + + case HLC_subband_cqi_mcs_CBA: + // this is the cba mcs uci for cba transmission + ((HLC_subband_cqi_mcs_CBA_5MHz *)o)->mcs = ulsch->harq_processes[harq_pid]->mcs; + ((HLC_subband_cqi_mcs_CBA_5MHz *)o)->crnti = rnti; + LOG_N(PHY,"fill uci for cba rnti %x, mcs %d \n", rnti, ulsch->harq_processes[harq_pid]->mcs); + break; + + case ue_selected: + LOG_E(PHY,"fill_CQI ue_selected CQI not supported yet!!!\n"); + mac_xface->macphy_exit("fill_CQI ue_selected CQI not supported yet!!!"); + break; + + default: + LOG_E(PHY,"unsupported CQI mode (%d)!!!\n",uci_format); + mac_xface->macphy_exit("unsupported CQI mode !!!"); + break; + + } + + break; + + case 50: + switch (uci_format) { + case wideband_cqi_rank1_2A: + ((wideband_cqi_rank1_2A_10MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((wideband_cqi_rank1_2A_10MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,9); + break; + + case wideband_cqi_rank2_2A: + ((wideband_cqi_rank2_2A_10MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); //FIXME: calculate rank2 cqi + ((wideband_cqi_rank2_2A_10MHz *)o)->cqi2 = sinr2cqi(sinr_tmp,trans_mode); //FIXME: calculate rank2 cqi + ((wideband_cqi_rank2_2A_10MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,9); + break; + + case HLC_subband_cqi_nopmi: + ((HLC_subband_cqi_nopmi_10MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_nopmi_10MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,9); + break; + + case HLC_subband_cqi_rank1_2A: + ((HLC_subband_cqi_rank1_2A_10MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank1_2A_10MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,9); + ((HLC_subband_cqi_rank1_2A_10MHz *)o)->pmi = quantize_wideband_pmi(meas,eNB_id); + break; + + case HLC_subband_cqi_rank2_2A: + // This has to be improved!!! + ((HLC_subband_cqi_rank2_2A_10MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank2_2A_10MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,9); + ((HLC_subband_cqi_rank2_2A_10MHz *)o)->cqi2 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank2_2A_10MHz *)o)->diffcqi2 = fill_subband_cqi(meas,eNB_id,trans_mode,9); + ((HLC_subband_cqi_rank2_2A_10MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,9); + break; + + case HLC_subband_cqi_mcs_CBA: + // this is the cba mcs uci for cba transmission + ((HLC_subband_cqi_mcs_CBA_10MHz *)o)->mcs = ulsch->harq_processes[harq_pid]->mcs; + ((HLC_subband_cqi_mcs_CBA_10MHz *)o)->crnti = rnti; + LOG_N(PHY,"fill uci for cba rnti %x, mcs %d \n", rnti, ulsch->harq_processes[harq_pid]->mcs); + break; + + case ue_selected: + LOG_E(PHY,"fill_CQI ue_selected CQI not supported yet!!!\n"); + mac_xface->macphy_exit("fill_CQI ue_selected CQI not supported yet!!!"); + break; + + default: + LOG_E(PHY,"unsupported CQI mode (%d)!!!\n",uci_format); + mac_xface->macphy_exit("unsupported CQI mode !!!"); + break; + + } + + break; + + case 100: + switch (uci_format) { + case wideband_cqi_rank1_2A: + ((wideband_cqi_rank1_2A_20MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((wideband_cqi_rank1_2A_20MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,13); + break; + + case wideband_cqi_rank2_2A: + ((wideband_cqi_rank2_2A_20MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); //FIXME: calculate rank2 cqi + ((wideband_cqi_rank2_2A_20MHz *)o)->cqi2 = sinr2cqi(sinr_tmp,trans_mode); //FIXME: calculate rank2 cqi + ((wideband_cqi_rank2_2A_20MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,13); + break; + + case HLC_subband_cqi_nopmi: + ((HLC_subband_cqi_nopmi_20MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_nopmi_20MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,13); + break; + + case HLC_subband_cqi_rank1_2A: + ((HLC_subband_cqi_rank1_2A_20MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank1_2A_20MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,13); + ((HLC_subband_cqi_rank1_2A_20MHz *)o)->pmi = quantize_wideband_pmi(meas,eNB_id); + break; + + case HLC_subband_cqi_rank2_2A: + // This has to be improved!!! + ((HLC_subband_cqi_rank2_2A_20MHz *)o)->cqi1 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank2_2A_20MHz *)o)->diffcqi1 = fill_subband_cqi(meas,eNB_id,trans_mode,13); + ((HLC_subband_cqi_rank2_2A_20MHz *)o)->cqi2 = sinr2cqi(sinr_tmp,trans_mode); + ((HLC_subband_cqi_rank2_2A_20MHz *)o)->diffcqi2 = fill_subband_cqi(meas,eNB_id,trans_mode,13); + ((HLC_subband_cqi_rank2_2A_20MHz *)o)->pmi = quantize_subband_pmi(meas,eNB_id,13); + break; + + case HLC_subband_cqi_mcs_CBA: + // this is the cba mcs uci for cba transmission + ((HLC_subband_cqi_mcs_CBA_20MHz *)o)->mcs = ulsch->harq_processes[harq_pid]->mcs; + ((HLC_subband_cqi_mcs_CBA_20MHz *)o)->crnti = rnti; + LOG_N(PHY,"fill uci for cba rnti %x, mcs %d \n", rnti, ulsch->harq_processes[harq_pid]->mcs); + break; + + case ue_selected: + LOG_E(PHY,"fill_CQI ue_selected CQI not supported yet!!!\n"); + mac_xface->macphy_exit("fill_CQI ue_selected CQI not supported yet!!!"); + break; + + default: + LOG_E(PHY,"unsupported CQI mode (%d)!!!\n",uci_format); + mac_xface->macphy_exit("unsupported CQI mode !!!"); + break; + + } + + break; + + } + + +} + +void reset_cba_uci(void *o) +{ + // this is the cba mcs uci for cba transmission + ((HLC_subband_cqi_mcs_CBA_5MHz *)o)->mcs = 0; //fixme + ((HLC_subband_cqi_mcs_CBA_5MHz *)o)->crnti = 0x0; +} + + +uint32_t pmi_extend(NR_DL_FRAME_PARMS *frame_parms,uint8_t wideband_pmi, uint8_t rank) +{ + + uint8_t i,wideband_pmi2; + uint32_t pmi_ex = 0; + + if (frame_parms->N_RB_DL!=25) { + LOG_E(PHY,"pmi_extend not yet implemented for anything else than 25PRB\n"); + return(-1); + } + + if (rank==0) { + wideband_pmi2=wideband_pmi&3; + for (i=0; i<14; i+=2) + pmi_ex|=(wideband_pmi2<<i); + } + else if (rank==1) { + wideband_pmi2=wideband_pmi&1; + for (i=0; i<7; i++) + pmi_ex|=(wideband_pmi2<<i); + } + else { + LOG_E(PHY,"unsupported rank\n"); + return(-1); + } + + return(pmi_ex); +} + + +int generate_ue_ulsch_params_from_dci(void *dci_pdu, + uint16_t rnti, + uint8_t nr_tti_rx, + DCI_format_t dci_format, + PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint16_t cba_rnti, + uint8_t eNB_id, + uint8_t use_srs) +{ + + uint8_t harq_pid; + uint8_t transmission_mode = ue->transmission_mode[eNB_id]; + ANFBmode_t AckNackFBMode; + NR_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; + NR_UE_DLSCH_t **dlsch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][0]; + PHY_MEASUREMENTS *meas = &ue->measurements; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + // uint32_t current_dlsch_cqi = ue->current_dlsch_cqi[eNB_id]; + + if(frame_parms->frame_type == TDD) + { + AckNackFBMode = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; + } + else + { + AckNackFBMode = 1; // 1: multiplexing for FDD + } + + uint32_t cqi_req; + uint32_t dai=3; + uint32_t cshift; + uint32_t TPC; + uint32_t ndi; + uint32_t mcs; + uint32_t rballoc,RIV_max; + uint16_t* RIV2first_rb_LUT; + uint16_t* RIV2nb_rb_LUT; + + // uint32_t hopping; + // uint32_t type; + + if (dci_format == format0) { + + if (!ulsch) + return -1; + + if (rnti == ra_rnti) + harq_pid = 0; + else + harq_pid = nr_subframe2harq_pid(frame_parms, + nr_pdcch_alloc2ul_frame(frame_parms,proc->frame_rx,nr_tti_rx), + nr_pdcch_alloc2ul_subframe(frame_parms,nr_tti_rx)); + + if (harq_pid == 255) { + LOG_E(PHY, "frame %d, nr_tti_rx %d, rnti %x, format %d: illegal harq_pid!\n", + proc->frame_rx, nr_tti_rx, rnti, dci_format); + return(-1); + } + + switch (frame_parms->N_RB_DL) { + case 6: + if (frame_parms->frame_type == TDD) { + cqi_req = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->cqi_req; + dai = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->dai; + cshift = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->cshift; + TPC = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC; + ndi = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->ndi; + mcs = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->hopping; + // type = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->type; + } else { + cqi_req = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->cqi_req; + cshift = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->cshift; + TPC = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->TPC; + ndi = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->ndi; + mcs = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->hopping; + // type = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->type; + } + + RIV_max = RIV_max6; + RIV2first_rb_LUT = RIV2first_rb_LUT6; + RIV2nb_rb_LUT = RIV2nb_rb_LUT6; + + break; + + case 25: + if (frame_parms->frame_type == TDD) { + cqi_req = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cqi_req; + dai = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->dai; + cshift = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift; + TPC = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->TPC; + ndi = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->ndi; + mcs = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->hopping; + // type = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->type; + } else { + cqi_req = ((DCI0_5MHz_FDD_t *)dci_pdu)->cqi_req; + cshift = ((DCI0_5MHz_FDD_t *)dci_pdu)->cshift; + TPC = ((DCI0_5MHz_FDD_t *)dci_pdu)->TPC; + ndi = ((DCI0_5MHz_FDD_t *)dci_pdu)->ndi; + mcs = ((DCI0_5MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI0_5MHz_FDD_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_5MHz_FDD_t *)dci_pdu)->hopping; + // type = ((DCI0_5MHz_FDD_t *)dci_pdu)->type; + } + + RIV_max = RIV_max25; + RIV2first_rb_LUT = RIV2first_rb_LUT25; + RIV2nb_rb_LUT = RIV2nb_rb_LUT25; + // printf("***********rballoc %d, first_rb %d, nb_rb %d (dci %p)\n",rballoc,ulsch->harq_processes[harq_pid]->first_rb,ulsch->harq_processes[harq_pid]->nb_rb,dci_pdu); + break; + + case 50: + if (frame_parms->frame_type == TDD) { + cqi_req = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->cqi_req; + dai = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->dai; + cshift = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->cshift; + TPC = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->TPC; + ndi = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->ndi; + mcs = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->hopping; + // type = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->type; + } else { + cqi_req = ((DCI0_10MHz_FDD_t *)dci_pdu)->cqi_req; + cshift = ((DCI0_10MHz_FDD_t *)dci_pdu)->cshift; + TPC = ((DCI0_10MHz_FDD_t *)dci_pdu)->TPC; + ndi = ((DCI0_10MHz_FDD_t *)dci_pdu)->ndi; + mcs = ((DCI0_10MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI0_10MHz_FDD_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_10MHz_FDD_t *)dci_pdu)->hopping; + // type = ((DCI0_10MHz_FDD_t *)dci_pdu)->type; + } + + RIV_max = RIV_max50; + RIV2first_rb_LUT = RIV2first_rb_LUT50; + RIV2nb_rb_LUT = RIV2nb_rb_LUT50; + + break; + + case 100: + if (frame_parms->frame_type == TDD) { + cqi_req = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->cqi_req; + dai = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->dai; + cshift = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->cshift; + TPC = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->TPC; + ndi = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->ndi; + mcs = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->hopping; + // type = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->type; + } else { + cqi_req = ((DCI0_20MHz_FDD_t *)dci_pdu)->cqi_req; + cshift = ((DCI0_20MHz_FDD_t *)dci_pdu)->cshift; + TPC = ((DCI0_20MHz_FDD_t *)dci_pdu)->TPC; + ndi = ((DCI0_20MHz_FDD_t *)dci_pdu)->ndi; + mcs = ((DCI0_20MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI0_20MHz_FDD_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_20MHz_FDD_t *)dci_pdu)->hopping; + // type = ((DCI0_20MHz_FDD_t *)dci_pdu)->type; + } + + RIV_max = RIV_max100; + RIV2first_rb_LUT = RIV2first_rb_LUT100; + RIV2nb_rb_LUT = RIV2nb_rb_LUT100; + + // printf("rb_alloc (20 MHz dci) %d\n",rballoc); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + + + if (rballoc > RIV_max) { + LOG_E(PHY,"frame %d, nr_tti_rx %d, rnti %x, format %d: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc[%d] > RIV_max[%d]\n", + proc->frame_rx, nr_tti_rx, rnti, dci_format,rballoc,RIV_max); + LOG_E(PHY,"Wrong DCI0 detection, do not transmit PUSCH for HARQID: %d\n",harq_pid); + ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0; + return(-1); + } + + + // indicate that this process is to be serviced in subframe n+4 + if ((rnti >= cba_rnti) && (rnti < p_rnti)) + ulsch->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1; //+=1 this indicates the number of dci / cba group: not supported in the data struct + else + { + ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + //LOG_I(PHY,"[HARQ-UL harqId: %d] DCI0 ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round); + + } + + ulsch->harq_processes[harq_pid]->TPC = TPC; + ulsch->harq_processes[harq_pid]->first_rb = RIV2first_rb_LUT[rballoc]; + ulsch->harq_processes[harq_pid]->nb_rb = RIV2nb_rb_LUT[rballoc]; + + if (ue->ul_power_control_dedicated[eNB_id].accumulationEnabled == 1) { + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d nr_tti_rx %d: f_pusch (ACC) %d, adjusting by %d (TPC %d)\n", + ue->Mod_id,harq_pid,proc->frame_rx,nr_tti_rx,ulsch->f_pusch, + delta_PUSCH_acc[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC); + ulsch->f_pusch += delta_PUSCH_acc[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC]; + } else { + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d nr_tti_rx %d: f_pusch (ABS) %d, adjusting to %d (TPC %d)\n", + ue->Mod_id,harq_pid,proc->frame_rx,nr_tti_rx,ulsch->f_pusch, + delta_PUSCH_abs[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC); + ulsch->f_pusch = delta_PUSCH_abs[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC]; + } + + if (ulsch->harq_processes[harq_pid]->first_tx==1) { + // ulsch->harq_processes[harq_pid]->Ndi = 1; + ulsch->harq_processes[harq_pid]->first_tx=0; + ulsch->harq_processes[harq_pid]->DCINdi= ndi; + ulsch->harq_processes[harq_pid]->round = 0; + } else { + if (ulsch->harq_processes[harq_pid]->DCINdi!=ndi) { // new SDU opportunity + // ulsch->harq_processes[harq_pid]->Ndi = 1; + ulsch->harq_processes[harq_pid]->DCINdi= ndi; + ulsch->harq_processes[harq_pid]->round = 0; + } else { + // ulsch->harq_processes[harq_pid]->Ndi = 0; + //ulsch->harq_processes[harq_pid]->round++; // This is done in phich RX + + //#ifdef DEBUG_PHICH + //LOG_I(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d Adaptative Retrans, NDI not toggled => Nack. maxHARQ_Tx %d \n", + // ue->Mod_id,harq_pid, + // proc->frame_rx, + // subframe, + // ulsch->Mlimit); + //#endif +/* + if (ulsch->harq_processes[harq_pid]->round > 0) // NACK detected on phich + { + // ulsch->harq_processes[harq_pid]->round++; already done on phich_rx + // ulsch->harq_processes[harq_pid] = ulsch->harq_processes[8]; + // LOG_I(PHY," Adaptative retransmission - copy temporary harq Process to current harq process. [harqId %d round %d] \n",harq_pid, ulsch->harq_processes[8]->round); + + if (ulsch->harq_processes[harq_pid]->round >= ulsch->Mlimit) //UE_mac_inst[eNB_id].scheduling_info.maxHARQ_Tx) + { + ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0; + ulsch->harq_processes[harq_pid]->round = 0; + ulsch->harq_processes[harq_pid]->status = IDLE; + //LOG_I(PHY," PUSCH MAX Retransmission acheived ==> flush harq buff (%d) \n",harq_pid); + //LOG_I(PHY," [HARQ-UL harqId: %d] Adaptative retransmission NACK MAX RETRANS(%d) ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, UE_mac_inst[eNB_id].scheduling_info.maxHARQ_Tx, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round); + } + else + { + // ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + uint8_t rv_table[4] = {0, 2, 3, 1}; + ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3]; + ulsch->O_RI = 0; + ulsch->O = 0; + ulsch->uci_format = HLC_subband_cqi_nopmi; + //LOG_I(PHY," [HARQ-UL harqId: %d] Adaptative retransmission NACK ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag,ulsch->harq_processes[harq_pid]->round); + } + } +*/ + } + } + + ulsch->harq_processes[harq_pid]->n_DMRS = cshift; + + //printf("nb_rb %d, first_rb %d (RIV %d)\n",ulsch->harq_processes[harq_pid]->nb_rb,ulsch->harq_processes[harq_pid]->first_rb,rballoc); + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + // ulsch->cba_rnti[0]=rnti; + } else { + ulsch->rnti = rnti; + } + + // printf("[PHY][UE] DCI format 0: harq_pid %d nb_rb %d, rballoc %d\n",harq_pid,ulsch->harq_processes[harq_pid]->nb_rb, + // ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->rballoc); + //Mapping of cyclic shift field in DCI format0 to n_DMRS2 (3GPP 36.211, Table 5.5.2.1.1-1) + if(cshift == 0) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 0; + else if(cshift == 1) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 6; + else if(cshift == 2) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 3; + else if(cshift == 3) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 4; + else if(cshift == 4) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 2; + else if(cshift == 5) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 8; + else if(cshift == 6) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 10; + else if(cshift == 7) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 9; + + + //reserved for cooperative communication + /* + if(ulsch->n_DMRS2 == 6) + ulsch->cooperation_flag = 2; + else + ulsch->cooperation_flag = 0; + */ + + if ((ulsch->harq_processes[harq_pid]->nb_rb>0) && (ulsch->harq_processes[harq_pid]->nb_rb < 25)) + ulsch->power_offset = ue_power_offsets[ulsch->harq_processes[harq_pid]->nb_rb-1]; + + // if (ulsch->harq_processes[harq_pid]->Ndi == 1) + // ulsch->harq_processes[harq_pid]->status = ACTIVE; + + + if (cqi_req == 1) { + + if( (AntennaInfoDedicated__transmissionMode_tm3 == transmission_mode) || (AntennaInfoDedicated__transmissionMode_tm4 == transmission_mode) ) + { + ulsch->O_RI = 1; + } + else + { + ulsch->O_RI = 0; + } + //ulsch->O_RI = 0; //we only support 2 antenna ports, so this is always 1 according to 3GPP 36.213 Table + + switch(transmission_mode) { + // The aperiodic CQI reporting mode is fixed for every transmission mode instead of being configured by higher layer signaling + case 1: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_mcs_CBA; + ulsch->o_RI[0] = 0; + } else if(meas->rank[eNB_id] == 0) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_nopmi; + ulsch->o_RI[0] = 0; + } else { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_nopmi; + ulsch->o_RI[0] = 1; + } + + break; + + case 2: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_mcs_CBA; + ulsch->o_RI[0] = 0; + } else if(meas->rank[eNB_id] == 0) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_nopmi; + ulsch->o_RI[0] = 0; + } else { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_nopmi; + ulsch->o_RI[0] = 1; + } + + break; + + case 3: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_mcs_CBA; + ulsch->o_RI[0] = 0; + } else if(meas->rank[eNB_id] == 0) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_nopmi; + ulsch->o_RI[0] = 0; + } else { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_nopmi; + ulsch->o_RI[0] = 1; + } + + break; + + case 4: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_mcs_CBA; + ulsch->o_RI[0] = 0; + } else if(meas->rank[eNB_id] == 0) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_wideband_cqi_rank1_2A_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_wideband_cqi_rank1_2A_5MHz; + break; + + case 50: + ulsch->O = sizeof_wideband_cqi_rank1_2A_10MHz; + break; + + case 100: + ulsch->O = sizeof_wideband_cqi_rank1_2A_20MHz; + break; + } + + ulsch->uci_format = wideband_cqi_rank1_2A; + ulsch->o_RI[0] = 0; + } else { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_wideband_cqi_rank2_2A_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_wideband_cqi_rank2_2A_5MHz; + break; + + case 50: + ulsch->O = sizeof_wideband_cqi_rank2_2A_10MHz; + break; + + case 100: + ulsch->O = sizeof_wideband_cqi_rank2_2A_20MHz; + break; + } + + ulsch->uci_format = wideband_cqi_rank2_2A; + ulsch->o_RI[0] = 1; + } + + break; + + case 5: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_mcs_CBA; + ulsch->o_RI[0] = 0; + } else if(meas->rank[eNB_id] == 0) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_wideband_cqi_rank1_2A_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_wideband_cqi_rank1_2A_5MHz; + break; + + case 50: + ulsch->O = sizeof_wideband_cqi_rank1_2A_10MHz; + break; + + case 100: + ulsch->O = sizeof_wideband_cqi_rank1_2A_20MHz; + break; + } + + ulsch->uci_format = wideband_cqi_rank1_2A; + ulsch->o_RI[0] = 0; + } else { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_wideband_cqi_rank2_2A_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_wideband_cqi_rank2_2A_5MHz; + break; + + case 50: + ulsch->O = sizeof_wideband_cqi_rank2_2A_10MHz; + break; + + case 100: + ulsch->O = sizeof_wideband_cqi_rank2_2A_20MHz; + break; + } + + ulsch->uci_format = wideband_cqi_rank2_2A; + ulsch->o_RI[0] = 1; + } + + break; + + case 6: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_mcs_CBA; + ulsch->o_RI[0] = 0; + } else if(meas->rank[eNB_id] == 0) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_wideband_cqi_rank1_2A_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_wideband_cqi_rank1_2A_5MHz; + break; + + case 50: + ulsch->O = sizeof_wideband_cqi_rank1_2A_10MHz; + break; + + case 100: + ulsch->O = sizeof_wideband_cqi_rank1_2A_20MHz; + break; + } + + ulsch->uci_format = wideband_cqi_rank1_2A; + ulsch->o_RI[0] = 0; + } else { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_wideband_cqi_rank2_2A_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_wideband_cqi_rank2_2A_5MHz; + break; + + case 50: + ulsch->O = sizeof_wideband_cqi_rank2_2A_10MHz; + break; + + case 100: + ulsch->O = sizeof_wideband_cqi_rank2_2A_20MHz; + break; + } + + ulsch->uci_format = wideband_cqi_rank2_2A; + ulsch->o_RI[0] = 1; + } + + break; + + case 7: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_mcs_CBA; + ulsch->o_RI[0] = 0; + } else if(meas->rank[eNB_id] == 0) { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_nopmi; + ulsch->o_RI[0] = 0; + } else { + switch (ue->frame_parms.N_RB_DL) { + case 6: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->O = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->uci_format = HLC_subband_cqi_nopmi; + ulsch->o_RI[0] = 1; + } + + break; + + default: + LOG_E(PHY,"Incorrect Transmission Mode \n"); + break; + } + } else { + ulsch->O_RI = 0; + ulsch->O = 0; + ulsch->uci_format = HLC_subband_cqi_nopmi; + } + + print_CQI(ulsch->o,ulsch->uci_format,eNB_id,ue->frame_parms.N_RB_DL); + + ulsch->bundling = 1-AckNackFBMode; + + if (frame_parms->frame_type == FDD) { + //int dl_subframe = (subframe<4) ? (subframe+6) : (subframe-4); + int dl_tti = nr_tti_rx; + + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_ack[dl_tti].send_harq_status>0) { // we have downlink transmission + ulsch->harq_processes[harq_pid]->O_ACK = 1; + } else { + ulsch->harq_processes[harq_pid]->O_ACK = 0; + } + /*LOG_I(PHY,"DCI 0 Processing: dl_subframe %d send_harq_status Odd %d send_harq_status Even %d harq_pid %d O_ACK %d\n", dl_subframe, + ue->dlsch[0][eNB_id][0]->harq_ack[dl_subframe].send_harq_status, + ue->dlsch[1][eNB_id][0]->harq_ack[dl_subframe].send_harq_status, + harq_pid, + ulsch->harq_processes[harq_pid]->O_ACK);*/ + + } else { + if (ulsch->bundling) + ulsch->harq_processes[harq_pid]->O_ACK = (dai == 3)? 0 : 1; + else + ulsch->harq_processes[harq_pid]->O_ACK = (dai >= 2)? 2 : (dai+1)&3; //(dai+1)&3; + + // ulsch->harq_processes[harq_pid]->V_UL_DAI = dai+1; + } + + dlsch[0]->harq_ack[nr_tti_rx].vDAI_UL = dai+1; + + + /*LOG_I(PHY, "[PUSCH %d] Format0 DCI %s, CQI_req=%d, cshift=%d, TPC=%d, DAI=%d, vDAI_UL[sf#%d]=%d, NDI=%d, MCS=%d, RBalloc=%d, first_rb=%d, harq_pid=%d, nb_rb=%d, subframe_scheduling_flag=%d" + " ulsch->bundling %d, O_ACK %d \n", + harq_pid, + (frame_parms->frame_type == TDD? "TDD" : "FDD"), + cqi_req, cshift, TPC, dai, subframe, dlsch[0]->harq_ack[subframe].vDAI_UL, ndi, mcs, rballoc, + ulsch->harq_processes[harq_pid]->first_rb, harq_pid, ulsch->harq_processes[harq_pid]->nb_rb, + ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, + ulsch->bundling, + ulsch->harq_processes[harq_pid]->O_ACK);*/ + + ulsch->beta_offset_cqi_times8 = beta_cqi[ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index];//18; + ulsch->beta_offset_ri_times8 = beta_ri[ue->pusch_config_dedicated[eNB_id].betaOffset_RI_Index];//10; + ulsch->beta_offset_harqack_times8 = beta_ack[ue->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index];//16; + + ulsch->Nsymb_pusch = 12-(frame_parms->Ncp<<1)-(use_srs==0?0:1); + ulsch->srs_active = use_srs; + + if ((rnti >= cba_rnti) && (rnti < p_rnti)) + ulsch->harq_processes[harq_pid]->status = CBA_ACTIVE; + else + ulsch->harq_processes[harq_pid]->status = ACTIVE; + + ulsch->harq_processes[harq_pid]->rvidx = 0; + + // ulsch->harq_processes[harq_pid]->calibration_flag =0; + if (mcs < 29) { + ulsch->harq_processes[harq_pid]->mcs = mcs; + // ulsch->harq_processes[harq_pid]->round = 0; + } else { + ulsch->harq_processes[harq_pid]->rvidx = mcs - 28; + if (ulsch->harq_processes[harq_pid]->round == 0) { + LOG_W(PHY,"PUSCH::mcs = %d and DCI0::mcs(%d) > 28 and round == %d\n", ulsch->harq_processes[harq_pid]->mcs, mcs, ulsch->harq_processes[harq_pid]->round); + } else { + LOG_D(PHY,"PUSCH::mcs = %d and DCI0::mcs(%d) > 28 and round == %d\n", ulsch->harq_processes[harq_pid]->mcs, mcs, ulsch->harq_processes[harq_pid]->round); + } + //LOG_E(PHY,"Fatal: mcs(%d) > 28!!! and round == 0\n", mcs); + } + ulsch->harq_processes[harq_pid]->TBS = TBStableUL[get_I_TBS_UL(ulsch->harq_processes[harq_pid]->mcs)][ulsch->harq_processes[harq_pid]->nb_rb-1]; + + /* + else if (ulsch->harq_processes[harq_pid]->mcs == 29) { + ulsch->harq_processes[harq_pid]->mcs = 4; + ulsch->harq_processes[harq_pid]->TBS = TBStable[get_I_TBS_UL(ulsch->harq_processes[harq_pid]->mcs)][ulsch->harq_processes[harq_pid]->nb_rb-1]; + // ulsch->harq_processes[harq_pid]->calibration_flag =1; + // printf("Auto-Calibration (UE): mcs %d, TBS %d, nb_rb %d\n",ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->TBS,ulsch->harq_processes[harq_pid]->nb_rb); + }*/ + ulsch->harq_processes[harq_pid]->Msc_initial = 12*ulsch->harq_processes[harq_pid]->nb_rb; + ulsch->harq_processes[harq_pid]->Nsymb_initial = ulsch->Nsymb_pusch; + + // a Ndi=1 automatically acknowledges previous PUSCH transmission + if (ue->ulsch_Msg3_active[eNB_id] == 1) + ue->ulsch_Msg3_active[eNB_id] = 0; + + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d, nr_tti_rx %d : Programming PUSCH with n_DMRS2 %d (cshift %d), nb_rb %d, first_rb %d, mcs %d, round %d, rv %d, ulsch_ue_Msg3_active %d\n", + ue->Mod_id,harq_pid, + proc->frame_rx,nr_tti_rx,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift,ulsch->harq_processes[harq_pid]->nb_rb,ulsch->harq_processes[harq_pid]->first_rb, + ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->round,ulsch->harq_processes[harq_pid]->rvidx, ue->ulsch_Msg3_active[eNB_id]); + + // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift; + +//printf("Format 0 DCI : ulsch (ue): AbsSubframe %d.%d nrb %d harq_pid %d round %d mcs %d\n",proc->frame_rx%1024,nr_tti_rx,ulsch->harq_processes[harq_pid]->nb_rb, + // harq_pid,ulsch->harq_processes[harq_pid]->round,ulsch->harq_processes[harq_pid]->mcs); + +#ifdef UE_DEBUG_TRACE + + LOG_I(PHY,"Format 0 DCI : ulsch (ue): AbsSubframe %d.%d\n",proc->frame_rx%1024,nr_tti_rx); + LOG_D(PHY,"Format 0 DCI : ulsch (ue): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): first_rb %d\n",ulsch->harq_processes[harq_pid]->first_rb); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): rballoc %d\n",rballoc); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): harq_pid %d\n",harq_pid); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): first_tx %d\n",ulsch->harq_processes[harq_pid]->first_tx); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): DCINdi %d\n",ulsch->harq_processes[harq_pid]->DCINdi); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): round %d\n",ulsch->harq_processes[harq_pid]->round); + //LOG_I(PHY,"Format 0 DCI :ulsch (ue): TBS %d\n",ulsch->harq_processes[harq_pid]->TBS); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): mcs %d\n",ulsch->harq_processes[harq_pid]->mcs); + //LOG_I(PHY,"Format 0 DCI :ulsch (ue): O %d\n",ulsch->O); + //LOG_I(PHY,"Format 0 DCI :ulsch (ue): cqiReq %d\n",cqi_req); + //if (frame_parms->frame_type == TDD) + // LOG_I(PHY,"Format 0 DCI :ulsch (ue): O_ACK/DAI %d/%d\n",ulsch->harq_processes[harq_pid]->O_ACK,dai); + //else + // LOG_I(PHY,"Format 0 DCI :ulsch (ue): O_ACK %d\n",ulsch->harq_processes[harq_pid]->O_ACK); + + LOG_D(PHY,"Format 0 DCI :ulsch (ue): Nsymb_pusch %d\n",ulsch->Nsymb_pusch); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2); + LOG_D(PHY,"Format 0 DCI :ulsch (ue): phich status %d\n",ulsch->harq_processes[harq_pid]->status); +#else + UNUSED_VARIABLE(dai); +#endif + return(0); + } else { + LOG_E(PHY,"frame %d, nr_tti_rx %d: FATAL ERROR, generate_ue_ulsch_params_from_dci, Illegal dci_format %d\n", + proc->frame_rx, nr_tti_rx,dci_format); + return(-1); + } + +} + +int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, + void *dci_pdu, + uint16_t rnti, + DCI_format_t dci_format, + uint8_t UE_id, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint16_t cba_rnti, + uint8_t use_srs) +{ + + uint8_t harq_pid; + uint32_t rb_alloc; + uint8_t transmission_mode=eNB->transmission_mode[UE_id]; + ANFBmode_t AckNackFBMode = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode; + LTE_eNB_ULSCH_t *ulsch=eNB->ulsch[UE_id]; + NR_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + int subframe = proc->subframe_tx; + + uint32_t cqi_req = 0; + uint32_t dai = 0; + uint32_t cshift = 0; + uint32_t TPC = 0; + uint32_t mcs = 0; + uint32_t rballoc = UINT32_MAX; + uint32_t RIV_max = 0; + // uint32_t hopping; + // uint32_t type; + +#ifdef DEBUG_DCI + printf("filling eNB ulsch params for rnti %x, dci format %d, dci %x, subframe %d\n", + rnti,dci_format,*(uint32_t*)dci_pdu,subframe); +#endif + + if (dci_format == format0) { + + harq_pid = nr_subframe2harq_pid(frame_parms, + nr_pdcch_alloc2ul_frame(frame_parms, + proc->frame_tx, + subframe), + nr_pdcch_alloc2ul_subframe(frame_parms,subframe)); + switch (frame_parms->N_RB_DL) { + case 6: + if (frame_parms->frame_type == TDD) { + cqi_req = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->cqi_req; + dai = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->dai; + cshift = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->cshift; + TPC = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC; + mcs = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->hopping; + // type = ((DCI0_1_5MHz_TDD_1_6_t *)dci_pdu)->type; + } else { + cqi_req = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->cqi_req; + cshift = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->cshift; + TPC = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->TPC; + mcs = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->hopping; + // type = ((DCI0_1_5MHz_FDD_t *)dci_pdu)->type; + } + + RIV_max = RIV_max6; + ulsch->harq_processes[harq_pid]->first_rb = RIV2first_rb_LUT6[rballoc]; + ulsch->harq_processes[harq_pid]->nb_rb = RIV2nb_rb_LUT6[rballoc]; + + break; + + case 25: + if (frame_parms->frame_type == TDD) { + cqi_req = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cqi_req; + dai = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->dai; + cshift = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift; + TPC = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->TPC; + mcs = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->hopping; + // type = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->type; + } else { + cqi_req = ((DCI0_5MHz_FDD_t *)dci_pdu)->cqi_req; + cshift = ((DCI0_5MHz_FDD_t *)dci_pdu)->cshift; + TPC = ((DCI0_5MHz_FDD_t *)dci_pdu)->TPC; + mcs = ((DCI0_5MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI0_5MHz_FDD_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_5MHz_FDD_t *)dci_pdu)->hopping; + // type = ((DCI0_5MHz_FDD_t *)dci_pdu)->type; + } + + RIV_max = RIV_max25; + ulsch->harq_processes[harq_pid]->first_rb = RIV2first_rb_LUT25[rballoc]; + ulsch->harq_processes[harq_pid]->nb_rb = RIV2nb_rb_LUT25[rballoc]; + + break; + + case 50: + if (frame_parms->frame_type == TDD) { + cqi_req = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->cqi_req; + dai = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->dai; + cshift = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->cshift; + TPC = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->TPC; + mcs = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->hopping; + // type = ((DCI0_10MHz_TDD_1_6_t *)dci_pdu)->type; + } else { + cqi_req = ((DCI0_10MHz_FDD_t *)dci_pdu)->cqi_req; + cshift = ((DCI0_10MHz_FDD_t *)dci_pdu)->cshift; + TPC = ((DCI0_10MHz_FDD_t *)dci_pdu)->TPC; + mcs = ((DCI0_10MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI0_10MHz_FDD_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_10MHz_FDD_t *)dci_pdu)->hopping; + // type = ((DCI0_10MHz_FDD_t *)dci_pdu)->type; + } + + RIV_max = RIV_max50; + ulsch->harq_processes[harq_pid]->first_rb = RIV2first_rb_LUT50[rballoc]; + ulsch->harq_processes[harq_pid]->nb_rb = RIV2nb_rb_LUT50[rballoc]; + + break; + + case 100: + if (frame_parms->frame_type == TDD) { + cqi_req = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->cqi_req; + dai = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->dai; + cshift = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->cshift; + TPC = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->TPC; + mcs = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->mcs; + rballoc = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->hopping; + // type = ((DCI0_20MHz_TDD_1_6_t *)dci_pdu)->type; + } else { + cqi_req = ((DCI0_20MHz_FDD_t *)dci_pdu)->cqi_req; + cshift = ((DCI0_20MHz_FDD_t *)dci_pdu)->cshift; + TPC = ((DCI0_20MHz_FDD_t *)dci_pdu)->TPC; + mcs = ((DCI0_20MHz_FDD_t *)dci_pdu)->mcs; + rballoc = ((DCI0_20MHz_FDD_t *)dci_pdu)->rballoc; + // hopping = ((DCI0_20MHz_FDD_t *)dci_pdu)->hopping; + // type = ((DCI0_20MHz_FDD_t *)dci_pdu)->type; + } + + RIV_max = RIV_max100; + ulsch->harq_processes[harq_pid]->first_rb = RIV2first_rb_LUT100[rballoc]; + ulsch->harq_processes[harq_pid]->nb_rb = RIV2nb_rb_LUT100[rballoc]; + + //printf("eNB: rb_alloc (20 MHz dci) %d\n",rballoc); + break; + + default: + LOG_E(PHY,"Invalid N_RB_DL %d\n", frame_parms->N_RB_DL); + DevParam (frame_parms->N_RB_DL, 0, 0); + break; + } + + rb_alloc = rballoc; + + if (rb_alloc>RIV_max) { + LOG_E(PHY,"Format 0: rb_alloc (%d) > RIV_max (%d)\n",rb_alloc,RIV_max); + mac_xface->macphy_exit("Format 0: error"); + return(-1); + } + +#ifdef DEBUG_DCI + printf("generate_eNB_ulsch_params_from_dci: subframe %d, rnti %x,harq_pid %d,cqi_req %d\n",subframe,rnti,harq_pid,cqi_req); +#endif + + ulsch->harq_processes[harq_pid]->dci_alloc = 1; + ulsch->harq_processes[harq_pid]->rar_alloc = 0; + ulsch->harq_processes[harq_pid]->TPC = TPC; + ulsch->harq_processes[harq_pid]->n_DMRS = cshift; + + + if (cqi_req == 1) { + /* 36.213 7.2.1 (release 10) says: + * "RI is only reported for transmission modes 3 and 4, + * as well as transmission modes 8 and 9 with PMI/RI reporting" + * This is for aperiodic reporting. + * TODO: deal with TM 8&9 correctly when they are implemented. + * TODO: deal with periodic reporting if we implement it. + */ + if (transmission_mode == 3 || transmission_mode == 4) + ulsch->harq_processes[harq_pid]->O_RI = 1; //we only support 2 antenna ports, so this is always 1 according to 3GPP 36.213 Table + else + ulsch->harq_processes[harq_pid]->O_RI = 0; + + switch(transmission_mode) { + // The aperiodic CQI reporting mode is fixed for every transmission mode instead of being configured by higher layer signaling + case 1: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_mcs_CBA; + } else { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_nopmi; + } + + break; + + case 2: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_mcs_CBA; + } else { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_nopmi; + } + + break; + + case 3: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_mcs_CBA; + } else { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_nopmi; + } + + break; + + case 4: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_mcs_CBA; + } else { + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_1_5MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_5MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_10MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_20MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_20MHz; + break; + + } + + ulsch->harq_processes[harq_pid]->uci_format = wideband_cqi_rank1_2A; + } + + break; + + case 5: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_mcs_CBA; + } else { + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_1_5MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_5MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_10MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_20MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = wideband_cqi_rank1_2A; + } + + break; + + case 6: + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_mcs_CBA_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_mcs_CBA; + } else { + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_1_5MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_5MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_10MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or2 = sizeof_wideband_cqi_rank2_2A_20MHz; + ulsch->harq_processes[harq_pid]->Or1 = sizeof_wideband_cqi_rank1_2A_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = wideband_cqi_rank1_2A; + } + + break; + + case 7: + ulsch->harq_processes[harq_pid]->Or2 = 0; + + switch (frame_parms->N_RB_DL) { + case 6: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_1_5MHz; + break; + + case 25: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_5MHz; + break; + + case 50: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_10MHz; + break; + + case 100: + ulsch->harq_processes[harq_pid]->Or1 = sizeof_HLC_subband_cqi_nopmi_20MHz; + break; + } + + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_nopmi; + break; + + default: + LOG_E(PHY,"Incorrect Transmission Mode \n"); + break; + } + } else { + ulsch->harq_processes[harq_pid]->O_RI = 0; + ulsch->harq_processes[harq_pid]->Or2 = 0; + ulsch->harq_processes[harq_pid]->Or1 = 0; + ulsch->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_nopmi; + } + + ulsch->bundling = 1-AckNackFBMode; + + if (frame_parms->frame_type == FDD) { + int dl_subframe = (subframe<4) ? (subframe+6) : (subframe-4); + + if (eNB->dlsch[UE_id][0]->subframe_tx[dl_subframe]>0) { // we have downlink transmission + ulsch->harq_processes[harq_pid]->O_ACK = 1; + } else { + ulsch->harq_processes[harq_pid]->O_ACK = 0; + } + } else { + if (ulsch->bundling) + ulsch->harq_processes[harq_pid]->O_ACK = (dai == 3)? 0 : 1; + else + ulsch->harq_processes[harq_pid]->O_ACK = (dai+1)&3; + + ulsch->harq_processes[harq_pid]->V_UL_DAI = dai+1; + } + + ulsch->beta_offset_cqi_times8 = beta_cqi[eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index];//18; + ulsch->beta_offset_ri_times8 = beta_ri[eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index];//10; + ulsch->beta_offset_harqack_times8 = beta_ack[eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index];//16; + + ulsch->harq_processes[harq_pid]->Nsymb_pusch = 12-(frame_parms->Ncp<<1)-(use_srs==0?0:1); + ulsch->harq_processes[harq_pid]->srs_active = use_srs; + + //Mapping of cyclic shift field in DCI format0 to n_DMRS2 (3GPP 36.211, Table 5.5.2.1.1-1) + if(cshift == 0) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 0; + else if(cshift == 1) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 6; + else if(cshift == 2) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 3; + else if(cshift == 3) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 4; + else if(cshift == 4) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 2; + else if(cshift == 5) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 8; + else if(cshift == 6) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 10; + else if(cshift == 7) + ulsch->harq_processes[harq_pid]->n_DMRS2 = 9; + + + LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d, subframe %d : Programming PUSCH with n_DMRS2 %d (cshift %d)\n", + eNB->Mod_id,harq_pid,proc->frame_tx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift); + + + + if (ulsch->harq_processes[harq_pid]->round == 0) { + if ((rnti >= cba_rnti) && (rnti < p_rnti)) + ulsch->harq_processes[harq_pid]->status = CBA_ACTIVE; + else + ulsch->harq_processes[harq_pid]->status = ACTIVE; + + ulsch->harq_processes[harq_pid]->rvidx = 0; + ulsch->harq_processes[harq_pid]->mcs = mcs; + // ulsch->harq_processes[harq_pid]->calibration_flag = 0; + //if (ulsch->harq_processes[harq_pid]->mcs) + /* + if (ulsch->harq_processes[harq_pid]->mcs == 29) { + ulsch->harq_processes[harq_pid]->mcs = 4; + // ulsch->harq_processes[harq_pid]->calibration_flag = 1; + // printf("Auto-Calibration (eNB): mcs %d, nb_rb %d\n",ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->nb_rb); + } + */ + ulsch->harq_processes[harq_pid]->TBS = TBStableUL[get_I_TBS_UL(ulsch->harq_processes[harq_pid]->mcs)][ulsch->harq_processes[harq_pid]->nb_rb-1]; + + ulsch->harq_processes[harq_pid]->Msc_initial = 12*ulsch->harq_processes[harq_pid]->nb_rb; + ulsch->harq_processes[harq_pid]->Nsymb_initial = ulsch->harq_processes[harq_pid]->Nsymb_pusch; + ulsch->harq_processes[harq_pid]->round = 0; + } else { + if (mcs>28) + ulsch->harq_processes[harq_pid]->rvidx = mcs - 28; + else { + ulsch->harq_processes[harq_pid]->rvidx = 0; + ulsch->harq_processes[harq_pid]->mcs = mcs; + } + + // ulsch->harq_processes[harq_pid]->round++; + } + + if ((rnti >= cba_rnti) && (rnti < p_rnti)) { + ulsch->cba_rnti[0] = rnti; + } else { + ulsch->rnti = rnti; + } + + //ulsch->n_DMRS2 = cshift; + +#ifdef DEBUG_DCI + printf("ulsch (eNB): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb); + printf("ulsch (eNB): first_rb %d\n",ulsch->harq_processes[harq_pid]->first_rb); + printf("ulsch (eNB): harq_pid %d\n",harq_pid); + printf("ulsch (eNB): round %d\n",ulsch->harq_processes[harq_pid]->round); + printf("ulsch (eNB): TBS %d\n",ulsch->harq_processes[harq_pid]->TBS); + printf("ulsch (eNB): mcs %d\n",ulsch->harq_processes[harq_pid]->mcs); + printf("ulsch (eNB): Or1 %d\n",ulsch->harq_processes[harq_pid]->Or1); + printf("ulsch (eNB): Nsymb_pusch %d\n",ulsch->harq_processes[harq_pid]->Nsymb_pusch); + printf("ulsch (eNB): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2); +#else + UNUSED_VARIABLE(dai); +#endif + return(0); + } else { + LOG_E(PHY,"generate_eNB_ulsch_params_from_dci, Illegal dci_format %d\n",dci_format); + return(-1); + } + +} + + +double sinr_eff_cqi_calc(PHY_VARS_NR_UE *ue, uint8_t eNB_id, uint8_t nr_tti_rx) +{ + uint8_t transmission_mode = ue->transmission_mode[eNB_id]; + PHY_MEASUREMENTS *meas = &ue->measurements; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int32_t **dl_channel_est = ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id]; + double *s_dB; + s_dB = ue->sinr_CQI_dB; + // NR_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; + //for the calculation of SINR_eff for CQI calculation + int count,a_rx,a_tx; + double abs_channel=0; + double channelx=0; + double channely=0; + double channelx_i=0; + double channely_i=0; + uint16_t q = quantize_subband_pmi(meas,eNB_id,7); + uint8_t qq; + + switch(transmission_mode) { + case 1: + for (count=0; count<frame_parms->N_RB_DL*12; count++) { + for(a_tx=0; a_tx<frame_parms->nb_antenna_ports_eNB; a_tx++) { + for (a_rx=0; a_rx<frame_parms->nb_antennas_rx; a_rx++) { + s_dB[count] = 10*log10(pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2],2) + pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2], + 2)) - meas->n0_power_avg_dB; + } + } + } + + break; + + case 2: + for (count=0; count<frame_parms->N_RB_DL*12; count++) { + abs_channel=0; + + for(a_tx=0; a_tx<frame_parms->nb_antenna_ports_eNB; a_tx++) { + for (a_rx=0; a_rx<frame_parms->nb_antennas_rx; a_rx++) { + abs_channel += (pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2],2) + pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2],2)); + } + } + + s_dB[count] = 10*log10(abs_channel/2) - meas->n0_power_avg_dB; + } + + break; + + case 5: + for (count=0; count<frame_parms->N_RB_DL*12; count++) { + channelx=0; + channely=0; + channelx_i=0; + channely_i=0; + qq = (q>>(((count/12)>>2)<<1))&3; + + //printf("pmi_alloc %d: rb %d, pmi %d\n",q,count/12,qq); + for(a_tx=0; a_tx<frame_parms->nb_antenna_ports_eNB; a_tx++) { + for (a_rx=0; a_rx<frame_parms->nb_antennas_rx; a_rx++) { + switch(qq) { + case 0: + if (channelx==0 || channely==0) { + channelx = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channelx_i = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely_i = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } else { + channelx += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channelx_i -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely_i -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } + + break; + + case 1: + if (channelx==0 || channely==0) { + channelx = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channelx_i = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely_i = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } else { + channelx -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channelx_i += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely_i += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } + + break; + + case 2: + if (channelx==0 || channely==0) { + channelx = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channelx_i = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely_i = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } else { + channelx -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channely += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channelx_i += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channely_i -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + } + + break; + + case 3: + if (channelx==0 || channely==0) { + channelx = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channelx_i = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely_i = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } else { + channelx += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channely -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channelx_i -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channely_i += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + } + + break; + + default: + printf("Problem in SINR Calculation for TM5 \n"); + break; + }//switch(qq) + }//a_rx + }//a_tx + + s_dB[count] = 10 * log10 ((pow(channelx,2) + pow(channely,2))/2) - 10 * log10 ((pow(channelx_i,2) + pow(channely_i,2))/2) - meas->n0_power_avg_dB; + }//count + + break; + + case 6: + for (count=0; count<frame_parms->N_RB_DL*12; count++) { + channelx=0; + channely=0; + qq = (q>>(((count/12)>>2)<<1))&3; + + //printf("pmi_alloc %d: rb %d, pmi %d\n",q,count/12,qq); + for(a_tx=0; a_tx<frame_parms->nb_antenna_ports_eNB; a_tx++) { + for (a_rx=0; a_rx<frame_parms->nb_antennas_rx; a_rx++) { + switch(qq) { + case 0: + if (channelx==0 || channely==0) { + channelx = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } else { + channelx += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } + + break; + + case 1: + if (channelx==0 || channely==0) { + channelx = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } else { + channelx -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } + + break; + + case 2: + if (channelx==0 || channely==0) { + channelx = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } else { + channelx -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channely += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + } + + break; + + case 3: + if (channelx==0 || channely==0) { + channelx = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + channely = ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + } else { + channelx += ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2]; + channely -= ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2]; + } + + break; + + default: + printf("Problem in SINR Calculation for TM6 \n"); + break; + }//switch(qq) + }//a_rx + }//a_tx + + s_dB[count] = 10 * log10 ((pow(channelx,2) + pow(channely,2))/2) - meas->n0_power_avg_dB; + }//count + + break; + + default: + printf("Problem in SINR Calculation for CQI \n"); + break; + } + + int ii; + double sinr_eff = 0; + double sinr_eff_qpsk=0; + double sinr_eff_qam16=0; + double sinr_eff_qam64=0; + double x = 0; + double I_qpsk=0; + double I_qam16=0; + double I_qam64=0; + double I_qpsk_avg=0; + double I_qam16_avg=0; + double I_qam64_avg=0; + double qpsk_max=12.2; + double qam16_max=19.2; + double qam64_max=25.2; + double sinr_min = -20; + int offset=0; + + + for (offset = 0; offset <= 24; offset++) { + for(ii=0; ii<12; ii++) { + //x is the sinr_dB in dB + x = s_dB[(offset*12)+ii]; + + if(x<sinr_min) { + I_qpsk +=0; + I_qam16 +=0; + I_qam64 +=0; + } else { + if(x>qpsk_max) + I_qpsk += 1; + else + I_qpsk += (q_qpsk[0]*pow(x,7) + q_qpsk[1]*pow(x,6) + q_qpsk[2]*pow(x,5) + q_qpsk[3]*pow(x,4) + q_qpsk[4]*pow(x,3) + q_qpsk[5]*pow(x,2) + q_qpsk[6]*x + q_qpsk[7]); + + if(x>qam16_max) + I_qam16 += 1; + else + I_qam16 += (q_qam16[0]*pow(x,7) + q_qam16[1]*pow(x,6) + q_qam16[2]*pow(x,5) + q_qam16[3]*pow(x,4) + q_qam16[4]*pow(x,3) + q_qam16[5]*pow(x,2) + q_qam16[6]*x + q_qam16[7]); + + if(x>qam64_max) + I_qam64 += 1; + else + I_qam64 += (q_qam64[0]*pow(x,7) + q_qam64[1]*pow(x,6) + q_qam64[2]*pow(x,5) + q_qam64[3]*pow(x,4) + q_qam64[4]*pow(x,3) + q_qam64[5]*pow(x,2) + q_qam64[6]*x + q_qam64[7]); + + } + } + } + + // averaging of accumulated MI + I_qpsk_avg = I_qpsk/(12*frame_parms->N_RB_DL); + I_qam16_avg = I_qam16/(12*frame_parms->N_RB_DL); + I_qam64_avg = I_qam64/(12*frame_parms->N_RB_DL); + + // I->SINR_effective Mapping + + sinr_eff_qpsk = (p_qpsk[0]*pow(I_qpsk_avg,7) + p_qpsk[1]*pow(I_qpsk_avg,6) + p_qpsk[2]*pow(I_qpsk_avg,5) + p_qpsk[3]*pow(I_qpsk_avg,4) + p_qpsk[4]*pow(I_qpsk_avg,3) + p_qpsk[5]*pow(I_qpsk_avg, + 2) + p_qpsk[6]*I_qpsk_avg + p_qpsk[7]); + + sinr_eff_qam16 = (p_qam16[0]*pow(I_qam16_avg,7) + p_qam16[1]*pow(I_qam16_avg,6) + p_qam16[2]*pow(I_qam16_avg,5) + p_qam16[3]*pow(I_qam16_avg,4) + p_qam16[4]*pow(I_qam16_avg, + 3) + p_qam16[5]*pow(I_qam16_avg,2) + p_qam16[6]*I_qam16_avg + p_qam16[7]); + + sinr_eff_qam64 = (p_qam64[0]*pow(I_qam64_avg,7) + p_qam64[1]*pow(I_qam64_avg,6) + p_qam64[2]*pow(I_qam64_avg,5) + p_qam64[3]*pow(I_qam64_avg,4) + p_qam64[4]*pow(I_qam64_avg, + 3) + p_qam64[5]*pow(I_qam64_avg,2) + p_qam64[6]*I_qam64_avg + p_qam64[7]); + sinr_eff = cmax3(sinr_eff_qpsk,sinr_eff_qam16,sinr_eff_qam64); + + //printf("SINR_Eff = %e\n",sinr_eff); + + return(sinr_eff); +} +// + + +#ifdef DEBUG_DLSCH_TOOLS +main() +{ + + int i; + uint8_t rah; + uint32_t rballoc; + + generate_RIV_tables(); + + rah = 0; + rballoc = 0x1fff; + printf("rballoc 0 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + rah = 1; + + rballoc = 0x1678; + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + + rballoc = 0xfffc; + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + rballoc = 0xfffd; + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + rballoc = 0xffff; + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + rballoc = 0xfffe; + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); +} + +#endif +#endif //(0) + diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index f791a1d597018454b88e0d17f7ff6b708e2fa95d..a4b8679f37d70e84102a4078835baea0f8ea0a47 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -52,7 +52,7 @@ void set_default_frame_parms_single(nfapi_config_request_t *config, NR_DL_FRAME_ //#define DEBUG_INITIAL_SYNCH -int pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) +int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) { uint8_t l,pbch_decoded,frame_mod4,pbch_tx_ant,dummy; @@ -95,6 +95,8 @@ int pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) pbch_decoded = 0; + printf("pbch_detection nid_cell %d\n",frame_parms->Nid_cell); + //for (frame_mod4=0; frame_mod4<4; frame_mod4++) { pbch_tx_ant = nr_rx_pbch(ue, &ue->proc.proc_rxtx[0], @@ -105,11 +107,8 @@ int pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) ue->high_speed_flag, frame_mod4); - if ((pbch_tx_ant>0) && (pbch_tx_ant<=2)) { - pbch_decoded = 1; + pbch_decoded = 0; //to be updated // break; - } - //} @@ -127,43 +126,6 @@ int pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) // ue->pbch_vars[0]->decoded_output[0] = ue->pbch_vars[0]->decoded_output[2]; // ue->pbch_vars[0]->decoded_output[2] = dummy; - // now check for Bandwidth of Cell - dummy = (ue->pbch_vars[0]->decoded_output[2]>>5)&7; - - switch (dummy) { - - case 0 : - frame_parms->N_RB_DL = 6; - break; - - case 1 : - frame_parms->N_RB_DL = 15; - break; - - case 2 : - frame_parms->N_RB_DL = 25; - break; - - case 3 : - frame_parms->N_RB_DL = 50; - break; - - case 4 : - frame_parms->N_RB_DL = 75; - break; - - case 5: - frame_parms->N_RB_DL = 100; - break; - - default: - LOG_E(PHY,"[UE%d] Initial sync: PBCH decoding: Unknown N_RB_DL\n",ue->Mod_id); - return -1; - break; - } - - - for(int i=0; i<RX_NB_TH;i++) { ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2; @@ -176,14 +138,11 @@ int pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) ue->proc.proc_rxtx[i].frame_tx = ue->proc.proc_rxtx[0].frame_rx; } #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully mode1_flag %d, tx_ant %d, frame %d, N_RB_DL %d, phich_duration %d, phich_resource %s!\n", + LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully mode1_flag %d, tx_ant %d, frame %d\n", ue->Mod_id, frame_parms->mode1_flag, pbch_tx_ant, - ue->proc.proc_rxtx[0].frame_rx, - frame_parms->N_RB_DL, - frame_parms->phich_config_common.phich_duration, - phich_resource); //frame_parms->phich_config_common.phich_resource); + ue->proc.proc_rxtx[0].frame_rx,); #endif return(0); } else { @@ -192,7 +151,6 @@ int pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) } -char phich_string[13][4] = {"","1/6","","1/2","","","one","","","","","","two"}; char duplex_string[2][4] = {"FDD","TDD"}; char prefix_string[2][9] = {"NORMAL","EXTENDED"}; @@ -260,11 +218,12 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) rx_sss_nr(ue,&metric_fdd_ncp,&phase_fdd_ncp); - set_default_frame_parms_single(config,&ue->frame_parms); + //set_default_frame_parms_single(config,&ue->frame_parms); nr_init_frame_parms_ue(config,&ue->frame_parms); nr_gold_pbch(ue); - ret = pbch_detection(ue,mode); + ret = nr_pbch_detection(ue,mode); + ret = -1; //to be deleted // write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); #ifdef DEBUG_INITIAL_SYNCH @@ -322,10 +281,6 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) } #endif - generate_pcfich_reg_mapping(frame_parms); - generate_phich_reg_mapping(frame_parms); - - ue->pbch_vars[0]->pdu_errors_conseq=0; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index bbb29877763a22c106b00fb282a5bc8dbaeb6340..3c062dbfa79636f975107a848bbb269e618e4945 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -31,20 +31,12 @@ */ #include "PHY/defs_nr_UE.h" #include "PHY/CODING/coding_extern.h" -#include "PHY/CODING/lte_interleaver_inline.h" -//#include "defs.h" -//#include "extern.h" #include "PHY/phy_extern_nr_ue.h" #include "PHY/sse_intrin.h" - -#ifdef PHY_ABSTRACTION -#include "SIMULATION/TOOLS/defs.h" -#endif - +#include "SIMULATION/TOOLS/sim.h" //#define DEBUG_PBCH 1 //#define DEBUG_PBCH_ENCODING -//#define INTERFERENCE_MITIGATION 1 #ifdef OPENAIR2 //#include "PHY_INTERFACE/defs.h" @@ -71,17 +63,17 @@ uint16_t nr_pbch_extract(int **rxdataF, int nushiftmod4 = frame_parms->nushift; for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { - - printf("extract_rbs (nushift %d): rx_offset=%d, symbol %d\n",frame_parms->nushift, - (rx_offset + (symbol*(frame_parms->ofdm_symbol_size))),symbol); - + rxF = &rxdataF[aarx][(rx_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; rxF_ext = &rxdataF_ext[aarx][symbol*(20*12)]; #ifdef DEBUG_PBCH + printf("extract_rbs (nushift %d): rx_offset=%d, symbol %d\n",frame_parms->nushift, + (rx_offset + (symbol*(frame_parms->ofdm_symbol_size))),symbol); int16_t *p = (int16_t *)rxF; - for (int i =0; i<240;i++){ + for (int i =0; i<8;i++){ printf("rxF [%d]= %d\n",i,rxF[i]); - printf("pbch pss %d %d @%p\n", p[2*i], p[2*i+1], &p[2*i]); + printf("pbch extract rxF %d %d addr %p\n", p[2*i], p[2*i+1], &p[2*i]); + printf("rxF ext addr %p\n", &rxF_ext[i]); } #endif @@ -105,13 +97,13 @@ uint16_t nr_pbch_extract(int **rxdataF, rxF+=12; rxF_ext+=9; } else { //symbol 2 - if ((rb < 4) && (rb >15)){ + if ((rb < 4) || (rb >15)){ for (i=0; i<12; i++) { if ((i!=nushiftmod4) && (i!=(nushiftmod4+4)) && (i!=(nushiftmod4+8))) { rxF_ext[j]=rxF[i]; - //printf("rxF ext[%d] = %d at %p\n",j,rxF_ext[j],&rxF[i]); + //printf("symbol2 rxF ext[%d] = %d at %p\n",j,rxF_ext[j],&rxF[i]); j++; } } @@ -128,7 +120,7 @@ uint16_t nr_pbch_extract(int **rxdataF, else dl_ch0 = &dl_ch_estimates[(aatx<<1)+aarx][0]; - printf("dl_ch0 addr %p\n",dl_ch0); + //printf("dl_ch0 addr %p\n",dl_ch0); dl_ch0_ext = &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*(20*12)]; @@ -140,8 +132,8 @@ uint16_t nr_pbch_extract(int **rxdataF, (i!=(nushiftmod4+4)) && (i!=(nushiftmod4+8))) { dl_ch0_ext[j]=dl_ch0[i]; - if ((rb==0) && (i<2)) - printf("dl ch0 ext[%d] = %d dl_ch0 [%d]= %d\n",j,dl_ch0_ext[j],i,dl_ch0[i]); + //if ((rb==0) && (i<2)) + //printf("dl ch0 ext[%d] = %d dl_ch0 [%d]= %d\n",j,dl_ch0_ext[j],i,dl_ch0[i]); j++; } } @@ -150,12 +142,13 @@ uint16_t nr_pbch_extract(int **rxdataF, dl_ch0_ext+=9; } else { //symbol 2 - if ((rb < 4) && (rb >15)){ + if ((rb < 4) || (rb >15)){ for (i=0; i<12; i++) { if ((i!=nushiftmod4) && (i!=(nushiftmod4+4)) && (i!=(nushiftmod4+8))) { dl_ch0_ext[j]=dl_ch0[i]; + //printf("symbol2 dl ch0 ext[%d] = %d dl_ch0 [%d]= %d\n",j,dl_ch0_ext[j],i,dl_ch0[i]); j++; } } @@ -181,7 +174,7 @@ int nr_pbch_channel_level(int **dl_ch_estimates_ext, uint32_t symbol) { - int16_t rb, nb_rb=6; + int16_t rb, nb_rb=20; uint8_t aatx,aarx; #if defined(__x86_64__) || defined(__i386__) @@ -193,19 +186,16 @@ int nr_pbch_channel_level(int **dl_ch_estimates_ext, #endif int avg1=0,avg2=0; - uint32_t nsymb = (frame_parms->Ncp==0) ? 7:6; - uint32_t symbol_mod = symbol % nsymb; - - for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antenna_ports_eNB;aatx++) + for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB;aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { //clear average level #if defined(__x86_64__) || defined(__i386__) avg128 = _mm_setzero_si128(); - dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol_mod*6*12]; + dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]; #elif defined(__arm__) avg128 = vdupq_n_s32(0); - dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol_mod*6*12]; + dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]; #endif for (rb=0; rb<nb_rb; rb++) { @@ -257,22 +247,24 @@ void nr_pbch_channel_compensation(int **rxdataF_ext, uint8_t output_shift) { - uint16_t rb,nb_rb=6; - uint8_t aatx,aarx,symbol_mod; + uint16_t rb,nb_rb=20; + uint8_t aatx,aarx; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128; #elif defined(__arm__) #endif - symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; - for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antenna_ports_eNB;aatx++) + for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB;aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { #if defined(__x86_64__) || defined(__i386__) - dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol_mod*6*12]; - rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol_mod*6*12]; - rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol_mod*6*12]; + dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]; + rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*20*12]; + rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]; + //printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]); + //printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol); + //printf("rxdataf_comp addr %p\n",&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]); #elif defined(__arm__) // to be filled in @@ -321,7 +313,6 @@ void nr_pbch_channel_compensation(int **rxdataF_ext, // print_shorts("ch:",dl_ch128+1); // print_shorts("pack:",rxdataF_comp128+1); - if (symbol_mod>1) { // multiply by conjugated channel mmtmpP0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) @@ -342,11 +333,7 @@ void nr_pbch_channel_compensation(int **rxdataF_ext, dl_ch128+=3; rxdataF128+=3; rxdataF_comp128+=3; - } else { - dl_ch128+=2; - rxdataF128+=2; - rxdataF_comp128+=2; - } + #elif defined(__arm__) // to be filled in #endif @@ -399,59 +386,30 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, #endif } -void nr_pbch_scrambling(NR_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; //this is c_init 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); - - } -} - void nr_pbch_unscrambling(NR_DL_FRAME_PARMS *frame_parms, - int8_t* llr, - uint32_t length, - uint8_t frame_mod4) + uint8_t* pbch_a, + uint32_t length) { int i; uint8_t reset; uint32_t x1, x2, s=0; + //printf("unscramb nid_cell %d\n",frame_parms->Nid_cell); + reset = 1; // x1 is set in first call to lte_gold_generic x2 = frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.6.1 - // msg("pbch_unscrambling: Nid_cell = %d\n",x2); for (i=0; i<length; i++) { if (i%32==0) { s = lte_gold_generic(&x1, &x2, reset); - // printf("lte_gold[%d]=%x\n",i,s); + //printf("lte_gold[%d]=%x\n",i,s); reset = 0; } - // take the quarter of the PBCH that corresponds to this frame - if ((i>=(frame_mod4*(length>>2))) && (i<((1+frame_mod4)*(length>>2)))) { - // if (((s>>(i%32))&1)==1) - - if (((s>>(i%32))&1)==0) - llr[i] = -llr[i]; - } + //printf("s = %d\n",((s>>(i%32))&1) ); + if (((s>>(i%32))&1)==1) + pbch_a[i] = 1-pbch_a[i]; } } @@ -501,19 +459,19 @@ void nr_pbch_quantize(int8_t *pbch_llr8, uint16_t i; for (i=0; i<len; i++) { - if (pbch_llr[i]>7) + /*if (pbch_llr[i]>7) pbch_llr8[i]=7; else if (pbch_llr[i]<-8) pbch_llr8[i]=-8; - else + else*/ pbch_llr8[i] = (char)(pbch_llr[i]); } } -static unsigned char dummy_w_rx[3*3*(16+PBCH_A)]; -static int8_t pbch_w_rx[3*3*(16+PBCH_A)],pbch_d_rx[96+(3*(16+PBCH_A))]; - +unsigned char sign(int8_t x) { + return (unsigned char)x >> 7; +} uint16_t nr_rx_pbch( PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, @@ -527,39 +485,40 @@ uint16_t nr_rx_pbch( PHY_VARS_NR_UE *ue, NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars; - uint8_t log2_maxh;//,aatx,aarx; + uint8_t log2_maxh; int max_h=0; int symbol,i; - uint32_t nsymb = (frame_parms->Ncp==0) ? 14:12; - uint16_t pbch_E; - uint8_t pbch_a[8]; - uint8_t RCC; + //uint8_t pbch_a[64]; + uint8_t *pbch_a = malloc(sizeof(uint8_t) * 32); ; int8_t *pbch_e_rx; uint8_t *decoded_output = nr_ue_pbch_vars->decoded_output; - uint16_t crc; + //uint16_t crc; + //short nr_demod_table[8] = {0,0,0,1,1,0,1,1}; + double nr_demod_table[8] = {0.707,0.707,0.707,-0.707,-0.707,0.707,-0.707,-0.707}; + double *demod_pbch_e = malloc (sizeof(double) * 864); + unsigned short idx_demod =0; + int8_t decoderState=0; + uint8_t decoderListSize = 8, pathMetricAppr = 0; + double aPrioriArray[frame_parms->pbch_polar_params.payloadBits]; // assume no a priori knowledge available about the payload. - int subframe_rx = proc->subframe_rx; + memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS); - // pbch_D = 16+PBCH_A; + //printf("nr_pbch_ue nid_cell %d\n",frame_parms->Nid_cell); - pbch_E = (frame_parms->Ncp==0) ? 1920 : 1728; //RE/RB * #RB * bits/RB (QPSK) - pbch_e_rx = &nr_ue_pbch_vars->llr[frame_mod4*(pbch_E>>2)]; -#ifdef DEBUG_PBCH - msg("[PBCH] starting symbol loop (Ncp %d, frame_mod4 %d,mimo_mode %d\n",frame_parms->Ncp,frame_mod4,mimo_mode); -#endif + for (int i=0; i<frame_parms->pbch_polar_params.payloadBits; i++) aPrioriArray[i] = NAN; + + int subframe_rx = proc->subframe_rx; + + pbch_e_rx = &nr_ue_pbch_vars->llr[0]; // clear LLR buffer - memset(nr_ue_pbch_vars->llr,0,pbch_E); + memset(nr_ue_pbch_vars->llr,0,NR_POLAR_PBCH_E); for (symbol=1; symbol<4; symbol++) { -#ifdef DEBUG_PBCH - msg("[PBCH] starting extract ofdm size %d\n",frame_parms->ofdm_symbol_size ); -#endif - - printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF); + //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF); //write_output("rxdataF0_pbch.m","rxF0pbch",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF,frame_parms->ofdm_symbol_size*4,2,1); nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF, @@ -570,7 +529,7 @@ uint16_t nr_rx_pbch( PHY_VARS_NR_UE *ue, high_speed_flag, frame_parms); #ifdef DEBUG_PBCH - msg("[PHY] PBCH Symbol %d\n",symbol); + msg("[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size ); msg("[PHY] PBCH starting channel_level\n"); #endif @@ -590,6 +549,8 @@ uint16_t nr_rx_pbch( PHY_VARS_NR_UE *ue, symbol, log2_maxh); // log2_maxh+I0_shift + //write_output("rxdataF_comp.m","rxFcomp",nr_ue_pbch_vars->rxdataF_comp,180,2,1); + /*if (frame_parms->nb_antennas_rx > 1) pbch_detection_mrc(frame_parms, nr_ue_pbch_vars->rxdataF_comp, @@ -598,25 +559,23 @@ uint16_t nr_rx_pbch( PHY_VARS_NR_UE *ue, if (mimo_mode == ALAMOUTI) { nr_pbch_alamouti(frame_parms,nr_ue_pbch_vars->rxdataF_comp,symbol); - // msg("[PBCH][RX] Alamouti receiver not yet implemented!\n"); - // return(-1); } else if (mimo_mode != SISO) { msg("[PBCH][RX] Unsupported MIMO mode\n"); return(-1); } - if (symbol>(nsymb>>1)+1) { + if (symbol==2) { nr_pbch_quantize(pbch_e_rx, - (short*)&(nr_ue_pbch_vars->rxdataF_comp[0][(symbol%(nsymb>>1))*72]), + (short*)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]), 144); pbch_e_rx+=144; } else { nr_pbch_quantize(pbch_e_rx, - (short*)&(nr_ue_pbch_vars->rxdataF_comp[0][(symbol%(nsymb>>1))*72]), - 96); + (short*)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]), + 360); - pbch_e_rx+=96; + pbch_e_rx+=360; } @@ -624,114 +583,45 @@ uint16_t nr_rx_pbch( PHY_VARS_NR_UE *ue, pbch_e_rx = nr_ue_pbch_vars->llr; - - - //un-scrambling #ifdef DEBUG_PBCH - msg("[PBCH] doing unscrambling\n"); -#endif - - - nr_pbch_unscrambling(frame_parms, - pbch_e_rx, - pbch_E, - frame_mod4); - - + //pbch_e_rx = &nr_ue_pbch_vars->llr[0]; - //un-rate matching -#ifdef DEBUG_PBCH - msg("[PBCH] doing un-rate-matching\n"); + short *p = (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][1*20*12]); + for (int cnt = 0; cnt < 8 ; cnt++) + printf("pbch rx llr %d rxdata_comp %d addr %p\n",*(pbch_e_rx+cnt), p[cnt], &p[0]); #endif - - memset(dummy_w_rx,0,3*3*(16+PBCH_A)); - RCC = generate_dummy_w_cc(16+PBCH_A, - dummy_w_rx); - - - lte_rate_matching_cc_rx(RCC,pbch_E,pbch_w_rx,dummy_w_rx,pbch_e_rx); - - sub_block_deinterleaving_cc((unsigned int)(PBCH_A+16), - &pbch_d_rx[96], - &pbch_w_rx[0]); - - memset(pbch_a,0,((16+PBCH_A)>>3)); - - - - - phy_viterbi_lte_sse2(pbch_d_rx+96,pbch_a,16+PBCH_A); - - // Fix byte endian of PBCH (bit 23 goes in first) - for (i=0; i<(PBCH_A>>3); i++) - decoded_output[(PBCH_A>>3)-i-1] = pbch_a[i]; - -#ifdef DEBUG_PBCH - - for (i=0; i<(PBCH_A>>3); i++) - msg("[PBCH] pbch_a[%d] = %x\n",i,decoded_output[i]); - -#endif //DEBUG_PBCH - + for (i=0; i<NR_POLAR_PBCH_E/2; i++){ + idx_demod = (sign(pbch_e_rx[i<<1])&1) ^ ((sign(pbch_e_rx[(i<<1)+1])&1)<<1); + demod_pbch_e[i<<1] = nr_demod_table[(idx_demod)<<1]; + demod_pbch_e[(i<<1)+1] = nr_demod_table[((idx_demod)<<1)+1]; #ifdef DEBUG_PBCH - msg("PBCH CRC %x : %x\n", - crc16(pbch_a,PBCH_A), - ((uint16_t)pbch_a[PBCH_A>>3]<<8)+pbch_a[(PBCH_A>>3)+1]); + if (i<16){ + printf("idx[%d]= %d\n", i , idx_demod); + printf("sign[%d]= %d sign[%d]= %d\n", i<<1 , sign(pbch_e_rx[i<<1]), (i<<1)+1 , sign(pbch_e_rx[(i<<1)+1])); + printf("demod_pbch_e2[%d] r = %2.3f i = %2.3f\n", i<<1 , demod_pbch_e[i<<1], demod_pbch_e[(i<<1)+1]);} #endif - - crc = (crc16(pbch_a,PBCH_A)>>16) ^ - (((uint16_t)pbch_a[PBCH_A>>3]<<8)+pbch_a[(PBCH_A>>3)+1]); - - if (crc == 0x0000) - return(1); - else if (crc == 0xffff) - return(2); - else if (crc == 0x5555) - return(4); - else - return(-1); - - -} - -#ifdef PHY_ABSTRACTION -uint16_t rx_pbch_emul(PHY_VARS_UE *phy_vars_ue, - uint8_t eNB_id, - uint8_t pbch_phase) -{ - - double bler=0.0;//, x=0.0; - double sinr=0.0; - uint16_t nb_rb = phy_vars_ue->frame_parms.N_RB_DL; - int16_t f; - uint8_t CC_id=phy_vars_ue->CC_id; - int frame_rx = phy_vars_ue->proc.proc_rxtx[0].frame_rx; - - // compute effective sinr - // TODO: adapt this to varible bandwidth - for (f=(nb_rb*6-3*12); f<(nb_rb*6+3*12); f++) { - if (f!=0) //skip DC - sinr += pow(10, 0.1*(phy_vars_ue->sinr_dB[f])); } - sinr = 10*log10(sinr/(6*12)); + + //polar decoding de-rate matching + decoderState = polar_decoder(demod_pbch_e, pbch_a, &frame_parms->pbch_polar_params, decoderListSize, aPrioriArray, pathMetricAppr); - bler = pbch_bler(sinr); + //for (i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++) + // printf("pbch_a[%d] = %u \n", i,pbch_a[i]); + + //un-scrambling + nr_pbch_unscrambling(frame_parms,pbch_a,NR_POLAR_PBCH_PAYLOAD_BITS); - LOG_D(PHY,"EMUL UE rx_pbch_emul: eNB_id %d, pbch_phase %d, sinr %f dB, bler %f \n", - eNB_id, - pbch_phase, - sinr, - bler); + // Fix byte endian + for (i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS); i++) + decoded_output[(NR_POLAR_PBCH_PAYLOAD_BITS)-i-1] = pbch_a[i]; + + //#ifdef DEBUG_PBCH + for (i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS); i++) + printf("unscrambling pbch_a[%d] = %d \n", i,pbch_a[i]); + //for (i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++) + // printf("[PBCH] decoder_output[%d] = %x\n",i,decoded_output[i]); + //#endif - if (pbch_phase == (frame_rx % 4)) { - if (uniformrandom() >= bler) { - memcpy(phy_vars_ue->pbch_vars[eNB_id]->decoded_output,PHY_vars_eNB_g[eNB_id][CC_id]->pbch_pdu,PBCH_PDU_SIZE); - return(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antenna_ports_eNB); - } else - return(-1); - } else - return(-1); } -#endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 3ff99c12d6f7a8d64dddba1884cf7fd1ff87853e..96806fbe82619a83870f748cbf5ccde5803d0fc8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -328,8 +328,43 @@ typedef struct { int8_t g_pucch; } NR_UE_DLSCH_t; +typedef enum {format0_0, + format0_1, + format1_0, + format1_1, + format2_0, + format2_1, + format2_2, + format2_3 + } NR_DCI_format_t; +typedef enum {nr_pucch_format0=0, + nr_pucch_format1, + nr_pucch_format2, + nr_pucch_format3, + nr_pucch_format4 + } NR_PUCCH_FMT_t; + +typedef struct { + /// Length of DCI in bits + uint8_t dci_length; + /// Aggregation level + uint8_t L; + /// Position of first CCE of the dci + int firstCCE; + /// flag to indicate that this is a RA response + boolean_t ra_flag; + /// rnti + rnti_t rnti; + /// Format + NR_DCI_format_t format; + /// search space + dci_space_t search_space; + /// DCI pdu + uint8_t dci_pdu[8]; +} NR_DCI_ALLOC_t; + /**@}*/ #endif diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index bf8020ecdae251e1adcdab1453759d7f779eabe8..4a25e62c771e6aed1d67317cb6a064e608c8276b 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -21,7 +21,7 @@ /*! \file PHY/defs_nr_UE.h \brief Top-level defines and structure definitions for nr ue - \author Guy De Souza, H. WANG + \author Guy De Souza, H. WANG, A. Mico Pereperez \date 2018 \version 0.1 \company Eurecom @@ -34,6 +34,8 @@ #include "defs_nr_common.h" +#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h" + #define _GNU_SOURCE #include <stdio.h> @@ -110,8 +112,8 @@ #define openair_sched_exit() exit(-1) -#define max(a,b) ((a)>(b) ? (a) : (b)) -#define min(a,b) ((a)<(b) ? (a) : (b)) +//#define max(a,b) ((a)>(b) ? (a) : (b)) +//#define min(a,b) ((a)<(b) ? (a) : (b)) #define bzero(s,n) (memset((s),0,(n))) @@ -140,7 +142,9 @@ #endif +#include "PHY/NR_UE_TRANSPORT/dci_nr.h" //#include "PHY/LTE_TRANSPORT/defs.h" +//#include "PHY/NR_UE_TRANSPORT/defs_nr.h" #include <pthread.h> #include "targets/ARCH/COMMON/common_lib.h" @@ -569,6 +573,207 @@ typedef struct { //MIMO_mode_t mimo_mode; } NR_UE_PDSCH_FLP; +#define NR_PDCCH_DEFS_NR_UE +#define NR_NBR_CORESET_ACT_BWP 3 // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0) +#define NR_NBR_SEARCHSPACE_ACT_BWP 10 // The number of SearchSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0) +#ifdef NR_PDCCH_DEFS_NR_UE + +#define NBR_NR_FORMATS 8 +#define NBR_NR_DCI_FIELDS 48 +// The following parameters define 'position' of each DCI field described in TS 38.212 +#define CARRIER_IND 0 +#define SUL_IND_0_1 1 +#define IDENTIFIER_DCI_FORMATS 2 +#define SLOT_FORMAT_IND 3 +#define PRE_EMPTION_IND 4 +#define TPC_CMD_NUMBER 5 +#define BLOCK_NUMBER 6 +#define BANDWIDTH_PART_IND 7 +#define FREQ_DOM_RESOURCE_ASSIGNMENT_UL 8 +#define FREQ_DOM_RESOURCE_ASSIGNMENT_DL 9 +#define TIME_DOM_RESOURCE_ASSIGNMENT 10 +#define VRB_TO_PRB_MAPPING 11 +#define PRB_BUNDLING_SIZE_IND 12 +#define RATE_MATCHING_IND 13 +#define ZP_CSI_RS_TRIGGER 14 +#define FREQ_HOPPING_FLAG 15 +#define TB1_MCS 16 +#define TB1_NDI 17 +#define TB1_RV 18 +#define TB2_MCS 19 +#define TB2_NDI 20 +#define TB2_RV 21 +#define MCS 22 +#define NDI 23 +#define RV 24 +#define HARQ_PROCESS_NUMBER 25 +#define DAI_ 26 +#define FIRST_DAI 27 +#define SECOND_DAI 28 +#define TPC_PUSCH 29 +#define TPC_PUCCH 30 +#define PUCCH_RESOURCE_IND 31 +#define PDSCH_TO_HARQ_FEEDBACK_TIME_IND 32 +#define SHORT_MESSAGE_IND 33 +#define SRS_RESOURCE_IND 34 +#define PRECOD_NBR_LAYERS 35 +#define ANTENNA_PORTS 36 +#define TCI 37 +#define SRS_REQUEST 38 +#define TPC_CMD_NUMBER_FORMAT2_3 39 +#define CSI_REQUEST 40 +#define CBGTI 41 +#define CBGFI 42 +#define PTRS_DMRS 43 +#define BETA_OFFSET_IND 44 +#define DMRS_SEQ_INI 45 +#define SUL_IND_0_0 46 +#define PADDING 47 + +typedef enum {bundle_n2=2,bundle_n3=3,bundle_n6=6} NR_UE_CORESET_REG_bundlesize_t; + +typedef enum {interleave_n2=2,interleave_n3=3,interleave_n6=6} NR_UE_CORESET_interleaversize_t; + +typedef struct { + //Corresponds to L1 parameter 'CORESET-REG-bundle-size' (see 38.211, section FFS_Section) + NR_UE_CORESET_REG_bundlesize_t reg_bundlesize; + //Corresponds to L1 parameter 'CORESET-interleaver-size' (see 38.211, 38.213, section FFS_Section) + NR_UE_CORESET_interleaversize_t interleaversize; + //Corresponds to L1 parameter 'CORESET-shift-index' (see 38.211, section 7.3.2.2) + int shiftIndex; +} NR_UE_CORESET_CCE_REG_MAPPING_t; + +typedef enum {allContiguousRBs=0,sameAsREGbundle=1} NR_UE_CORESET_precoder_granularity_t; + +typedef struct { + /* + * define CORESET structure according to 38.331 + * + * controlResourceSetId: Corresponds to L1 parameter 'CORESET-ID' + * Value 0 identifies the common CORESET configured in MIB and in ServingCellConfigCommon + * Values 1..maxNrofControlResourceSets-1 identify CORESETs configured by dedicated signalling + * frequencyDomainResources: BIT STRING (SIZE (45)) + * Corresponds to L1 parameter 'CORESET-freq-dom'(see 38.211, section 7.3.2.2) + * Frequency domain resources for the CORESET. Each bit corresponds a group of 6 RBs, with grouping starting from PRB 0, + * which is fully contained in the bandwidth part within which the CORESET is configured. + * duration: INTEGER (1..maxCoReSetDuration) + * Corresponds to L1 parameter 'CORESET-time-duration' (see 38.211, section 7.3.2.2FFS_Section) + * Contiguous time duration of the CORESET in number of symbols + * cce-REG-MappingType: interleaved + * reg-BundleSize: ENUMERATED {n2, n3, n6} + * interleaverSize: ENUMERATED {n2, n3, n6} + * shiftIndex: INTEGER + * nonInterleaved NULL + * precoderGranularity: ENUMERATED {sameAsREG-bundle, allContiguousRBs} + * Corresponds to L1 parameter 'CORESET-precoder-granuality' (see 38.211, sections 7.3.2.2 and 7.4.1.3.2) + * tci-StatesPDCCH: SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL + * A subset of the TCI states defined in TCI-States used for providing QCL relationships between the DL RS(s) + * in one RS Set (TCI-State) and the PDCCH DMRS ports. + * Corresponds to L1 parameter 'TCI-StatesPDCCH' (see 38.214, section FFS_Section) + * tci-PresentInDCI: ENUMERATED {enabled} OPTIONAL + * Corresponds to L1 parameter 'TCI-PresentInDCI' (see 38,213, section 5.1.5) + * pdcch-DMRS-ScramblingID: BIT STRING (SIZE (16)) OPTIONAL + * PDCCH DMRS scrambling initalization. + * Corresponds to L1 parameter 'PDCCH-DMRS-Scrambling-ID' (see 38.214, section 5.1) + * When the field is absent the UE applies the value '0'. + */ + int controlResourceSetId; + uint64_t frequencyDomainResources; + int duration; + NR_UE_CORESET_CCE_REG_MAPPING_t cce_reg_mappingType; + NR_UE_CORESET_precoder_granularity_t precoderGranularity; + int tciStatesPDCCH; + int tciPresentInDCI; + uint16_t pdcchDMRSScramblingID; + +} NR_UE_PDCCH_CORESET; + +// Slots for PDCCH Monitoring configured as periodicity and offset +typedef enum {nr_sl1=1,nr_sl2=2,nr_sl4=4,nr_sl5=5,nr_sl8=8,nr_sl10=10,nr_sl16=16,nr_sl20=20} NR_UE_SLOT_PERIOD_OFFSET_t; +typedef enum {nc0=0,nc1=1,nc2=2,nc3=3,nc4=4,nc5=5,nc6=6,nc8=8} NR_UE_SEARCHSPACE_nbrCAND_t; +typedef enum {nsfi1=1,nsfi2=2} NR_UE_SEARCHSPACE_nbrCAND_SFI_t; +typedef enum {n2_3_1=1,n2_3_2=2} NR_UE_SEARCHSPACE_nbrCAND_2_3_t; +typedef enum {cformat0_0_and_1_0=0,cformat2_0=2,cformat2_1=3,cformat2_2=4,cformat2_3=5} NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t; +typedef enum {uformat0_0_and_1_0=0,uformat0_1_and_1_1=1} NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t; +// Monitoring periodicity of SRS PDCCH in number of slots for DCI format 2-3 +// Corresponds to L1 parameter 'SRS-Num-PDCCH-cand' (see 38.212, 38.213, section 7.3.1, 11.3) +typedef enum {mp1=1,mp2=2,mp4=4,mp5=5,mp8=8,mp10=10,mp16=16,mp20=20} NR_UE_SEARCHSPACE_MON_PERIOD_t; +//typedef enum {n1=1,n2=2} NR_UE_SEARCHSPACE_nbrCAND_2_3_t; + // The number of PDCCH candidates for DCI format 2-3 for the configured aggregation level. + // Corresponds to L1 parameter 'SRS-Num-PDCCH-cand' (see 38.212, 38.213, section 7.3.1, 11.3) +typedef enum {common=0,ue_specific=1} NR_SEARCHSPACE_TYPE_t; + +typedef struct { + +/* + * searchSpaceType: Indicates whether this is a common search space (present) or a UE specific search space (CHOICE) + * as well as DCI formats to monitor for (description in struct NR_UE_PDCCH_SEARCHSPACE_TYPE + * common: Configures this search space as common search space (CSS) and DCI formats to monitor + * ue-Specific: Configures this search space as UE specific search space (USS) + * The UE monitors the DCI format with CRC scrambled by + * C-RNTI, CS-RNTI (if configured), TC-RNTI (if a certain condition is met), + * and SP-CSI-RNTI (if configured) + */ + + NR_SEARCHSPACE_TYPE_t type; + NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t common_dci_formats; + //NR_UE_SEARCHSPACE_nbrCAND_t nrofCandidates_SFI_aggr_level[5]; // FIXME! A table of five enum elements + NR_UE_SEARCHSPACE_nbrCAND_SFI_t sfi_nrofCandidates_aggrlevel1; + NR_UE_SEARCHSPACE_nbrCAND_SFI_t sfi_nrofCandidates_aggrlevel2; + NR_UE_SEARCHSPACE_nbrCAND_SFI_t sfi_nrofCandidates_aggrlevel4; + NR_UE_SEARCHSPACE_nbrCAND_SFI_t sfi_nrofCandidates_aggrlevel8; + NR_UE_SEARCHSPACE_nbrCAND_SFI_t sfi_nrofCandidates_aggrlevel16; + NR_UE_SEARCHSPACE_MON_PERIOD_t srs_monitoringPeriodicity2_3; + NR_UE_SEARCHSPACE_nbrCAND_2_3_t srs_nrofCandidates; + NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t ue_specific_dci_formats; + +} NR_UE_PDCCH_SEARCHSPACE_TYPE; + +typedef struct { +/* + * define SearchSpace structure according to 38.331 + * + * searchSpaceId: Identity of the search space. SearchSpaceId = 0 identifies the SearchSpace configured via PBCH (MIB) + * The searchSpaceId is unique among the BWPs of a Serving Cell + * controlResourceSetId: CORESET applicable for this SearchSpace + * 0 identifies the common CORESET configured in MIB + * 1..maxNrofControlResourceSets-1 identify CORESETs configured by dedicated signalling + * monitoringSlotPeriodicityAndOffset: + * Slots for PDCCH Monitoring configured as periodicity and offset. + * Corresponds to L1 parameters 'Montoring-periodicity-PDCCH-slot' and + * 'Montoring-offset-PDCCH-slot' (see 38.213, section 10) + * monitoringSymbolsWithinSlot: + * Symbols for PDCCH monitoring in the slots configured for PDCCH monitoring + * The most significant (left) bit represents the first OFDM in a slot + * + * nrofCandidates: Number of PDCCH candidates per aggregation level + * + * searchSpaceType: Indicates whether this is a common search space (present) or a UE specific search space + * as well as DCI formats to monitor for (description in struct NR_UE_PDCCH_SEARCHSPACE_TYPE + * common: Configures this search space as common search space (CSS) and DCI formats to monitor + * ue-Specific: Configures this search space as UE specific search space (USS) + * The UE monitors the DCI format with CRC scrambled by + * C-RNTI, CS-RNTI (if configured), TC-RNTI (if a certain condition is met), + * and SP-CSI-RNTI (if configured) + */ + // INTEGER (0..maxNrofSearchSpaces-1) (0..40-1) + int searchSpaceId; + int controlResourceSetId; + // FIXME! Verify type to be used for this parameter (sl1, sl2, sl4, sl5, sl8, sl10, sl16, sl20). Maybe enum. + NR_UE_SLOT_PERIOD_OFFSET_t monitoringSlotPeriodicityAndOffset; + int monitoringSlotPeriodicityAndOffset_offset; + // bit string size 14. Bitmap to indicate symbols within slot where PDCCH has to be monitored + // the MSB (left) bit represents first OFDM in slot + uint16_t monitoringSymbolWithinSlot; + NR_UE_SEARCHSPACE_nbrCAND_t nrofCandidates_aggrlevel1; + NR_UE_SEARCHSPACE_nbrCAND_t nrofCandidates_aggrlevel2; + NR_UE_SEARCHSPACE_nbrCAND_t nrofCandidates_aggrlevel4; + NR_UE_SEARCHSPACE_nbrCAND_t nrofCandidates_aggrlevel8; + NR_UE_SEARCHSPACE_nbrCAND_t nrofCandidates_aggrlevel16; + NR_UE_PDCCH_SEARCHSPACE_TYPE searchSpaceType; + +} NR_UE_PDCCH_SEARCHSPACE; +#endif typedef struct { /// \brief Pointers to extracted PDCCH symbols in frequency-domain. /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx @@ -621,6 +826,13 @@ typedef struct { //Check for specific DCIFormat and AgregationLevel uint8_t dciFormat; uint8_t agregationLevel; + #ifdef NR_PDCCH_DEFS_NR_UE + // CORESET structure, where maximum number of CORESETs to be handled is 3 (according to 38.331 V15.1.0) + NR_UE_PDCCH_CORESET coreset[NR_NBR_CORESET_ACT_BWP]; + // SEARCHSPACE structure, where maximum number of SEARCHSPACEs to be handled is 10 (according to 38.331 V15.1.0) + // Each SearchSpace is associated with one ControlResourceSet + NR_UE_PDCCH_SEARCHSPACE searchSpace[NR_NBR_SEARCHSPACE_ACT_BWP]; + #endif } NR_UE_PDCCH; #define PBCH_A 24 diff --git a/openair1/PHY/phy_vars_nr_ue.h b/openair1/PHY/phy_vars_nr_ue.h index a179f509c61ad2169f1173b5fc862eb968585d19..476d64f104897b2f92e25003564d1f19aa90c4d1 100644 --- a/openair1/PHY/phy_vars_nr_ue.h +++ b/openair1/PHY/phy_vars_nr_ue.h @@ -44,6 +44,7 @@ int16_t *primary_synch2_time; //PHY_VARS *PHY_vars; #ifndef OCP_FRAMEWORK PHY_VARS_NR_UE ***PHY_vars_UE_g; +PHY_VARS_eNB ***PHY_vars_eNB_g; LTE_DL_FRAME_PARMS *lte_frame_parms_g; #else PHY_VARS_NR_UE * PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs]={NULL}; diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h new file mode 100644 index 0000000000000000000000000000000000000000..a6f2beb131278227e20dceb991920ea110238af4 --- /dev/null +++ b/openair1/SCHED_NR_UE/defs.h @@ -0,0 +1,373 @@ +/* + * 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 + */ + +/* + \author R. Knopp, F. Kaltenberger + \company EURECOM + \email knopp@eurecom.fr +*/ + +#ifndef __openair_SCHED_H__ +#define __openair_SCHED_H__ + +#include "PHY/defs_nr_UE.h" + + +/*enum THREAD_INDEX { OPENAIR_THREAD_INDEX = 0, + TOP_LEVEL_SCHEDULER_THREAD_INDEX, + DLC_SCHED_THREAD_INDEX, + openair_SCHED_NB_THREADS + };*/ // do not modify this line + + +#define OPENAIR_THREAD_PRIORITY 255 + + +#define OPENAIR_THREAD_STACK_SIZE PTHREAD_STACK_MIN //4096 //RTL_PTHREAD_STACK_MIN*6 +//#define DLC_THREAD_STACK_SIZE 4096 //DLC stack size +//#define UE_SLOT_PARALLELISATION +//#define UE_DLSCH_PARALLELISATION + +/*enum openair_SCHED_STATUS { + openair_SCHED_STOPPED=1, + openair_SCHED_STARTING, + openair_SCHED_STARTED, + openair_SCHED_STOPPING +};*/ + +/*enum openair_ERROR { + // HARDWARE CAUSES + openair_ERROR_HARDWARE_CLOCK_STOPPED= 1, + + // SCHEDULER CAUSE + openair_ERROR_OPENAIR_RUNNING_LATE, + openair_ERROR_OPENAIR_SCHEDULING_FAILED, + + // OTHERS + openair_ERROR_OPENAIR_TIMING_OFFSET_OUT_OF_BOUNDS, +};*/ + +/*enum openair_SYNCH_STATUS { + openair_NOT_SYNCHED=1, + openair_SYNCHED, + openair_SCHED_EXIT +};*/ + +/*enum openair_HARQ_TYPE { + openair_harq_DL = 0, + openair_harq_UL, + openair_harq_RA +};*/ + +#define DAQ_AGC_ON 1 +#define DAQ_AGC_OFF 0 + + +/** @addtogroup _PHY_PROCEDURES_ + * @{ + */ + + +/*! \brief Top-level entry routine for UE procedures. Called every slot by process scheduler. In even slots, it performs RX functions from previous subframe (if required). On odd slots, it generate TX waveform for the following subframe. + @param phy_vars_ue Pointer to UE variables on which to act + @param eNB_id ID of eNB on which to act + @param abstraction_flag Indicator of PHY abstraction + @param mode calibration/debug mode + @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying + @param *phy_vars_rn pointer to RN variables +*/ +void phy_procedures_UE_lte(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,relaying_type_t r_type); +#if defined(Rel10) || defined(Rel14) +/*! \brief Top-level entry routine for relay node procedures actinf as UE. This proc will make us of the existing UE procs. + @param last_slot Index of last slot (0-19) + @param next_slot Index of next_slot (0-19) + @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying +*/ +int phy_procedures_RN_UE_RX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type); +#endif + +/*! \brief Scheduling for UE TX procedures in normal subframes. + @param phy_vars_ue Pointer to UE variables on which to act + @param proc Pointer to RXn-TXnp4 proc information + @param eNB_id Local id of eNB on which to act + @param abstraction_flag Indicator of PHY abstraction + @param mode calib/normal mode + @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying +*/ +void phy_procedures_UE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type); +/*! \brief Scheduling for UE RX procedures in normal subframes. + @param last_slot Index of last slot (0-19) + @param phy_vars_ue Pointer to UE variables on which to act + @param proc Pointer to RXn_TXnp4 proc information + @param eNB_id Local id of eNB on which to act + @param abstraction_flag Indicator of PHY abstraction + @param mode calibration/debug mode + @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying + @param phy_vars_rn pointer to RN variables +*/ +int phy_procedures_UE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,relaying_type_t r_type); +int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,relaying_type_t r_type); + +#ifdef UE_SLOT_PARALLELISATION +void *UE_thread_slot1_dl_processing(void *arg); +#endif + +/*! \brief Scheduling for UE TX procedures in TDD S-subframes. + @param phy_vars_ue Pointer to UE variables on which to act + @param eNB_id Local id of eNB on which to act + @param abstraction_flag Indicator of PHY abstraction + @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying +*/ +void phy_procedures_UE_S_TX(PHY_VARS_NR_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,relaying_type_t r_type); + +/*! \brief Scheduling for UE RX procedures in TDD S-subframes. + @param phy_vars_ue Pointer to UE variables on which to act + @param eNB_id Local id of eNB on which to act + @param abstraction_flag Indicator of PHY abstraction + @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying +*/ +void phy_procedures_UE_S_RX(PHY_VARS_NR_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag, relaying_type_t r_type); + + +/*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index. + @param frame_parms Pointer to DL frame parameter descriptor + @param subframe Subframe index + @returns Subframe type (DL,UL,S) +*/ + + +nr_subframe_t nr_subframe_select(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe); + + +/*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index. Same as nr_subframe_select, except that it uses the Mod_id and is provided as a service to the MAC scheduler. + @param Mod_id Index of eNB + @param CC_id Component Carrier Index + @param subframe Subframe index + @returns Subframe type (DL,UL,S) +*/ +nr_subframe_t nr_get_subframe_direction(uint8_t Mod_id, uint8_t CC_id,uint8_t subframe); + +/*! \brief Function to compute timing of Msg3 transmission on UL-SCH (first UE transmission in RA procedure). This implements the timing in paragraph a) from Section 6.1.1 in 36.213 (p. 17 in version 8.6). Used by eNB upon transmission of random-access response (RA_RNTI) to program corresponding ULSCH reception procedure. Used by UE upon reception of random-access response (RA_RNTI) to program corresponding ULSCH transmission procedure. This does not support the UL_delay field in RAR (always assumed to be 0). + @param frame_parms Pointer to DL frame parameter descriptor + @param current_subframe Index of subframe where RA_RNTI was received + @param current_frame Index of frame where RA_RNTI was received + @param frame Frame index where Msg3 is to be transmitted (n+6 mod 10 for FDD, different for TDD) + @param subframe subframe index where Msg3 is to be transmitted (n, n+1 or n+2) +*/ +void nr_get_Msg3_alloc(NR_DL_FRAME_PARMS *frame_parms, + uint8_t current_subframe, + uint32_t current_frame, + uint32_t *frame, + uint8_t *subframe); + +/*! \brief Function to compute timing of Msg3 retransmission on UL-SCH (first UE transmission in RA procedure). + @param frame_parms Pointer to DL frame parameter descriptor + @param current_subframe Index of subframe where RA_RNTI was received + @param current_frame Index of frame where RA_RNTI was received + @param frame Frame index where Msg3 is to be transmitted (n+6 mod 10 for FDD, different for TDD) + @param subframe subframe index where Msg3 is to be transmitted (n, n+1 or n+2) +*/ +void nr_get_Msg3_alloc_ret(NR_DL_FRAME_PARMS *frame_parms, + uint8_t current_subframe, + uint32_t current_frame, + uint32_t *frame, + uint8_t *subframe); + +/*! \brief Get ULSCH harq_pid for Msg3 from RAR subframe. This returns n+k mod 10 (k>6) and corresponds to the rule in Section 6.1.1 from 36.213 + @param frame_parms Pointer to DL Frame Parameters + @param frame Frame index + @param current_subframe subframe of RAR transmission + @returns harq_pid (0 ... 7) + */ +uint8_t nr_get_Msg3_harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t current_subframe); + +/*! \brief Get ULSCH harq_pid from PHICH subframe + @param frame_parms Pointer to DL Frame Parameters + @param subframe subframe of PHICH + @returns harq_pid (0 ... 7) + */ + +/*! \brief Function to indicate failure of contention resolution or RA procedure. It places the UE back in PRACH mode. + @param Mod_id Instance index of UE + @param CC_id Component Carrier Index + @param eNB_index Index of eNB + */ +void ra_failed(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); + +/*! \brief Function to indicate success of contention resolution or RA procedure. + @param Mod_id Instance index of UE + @param CC_id Component Carrier Index + @param eNB_index Index of eNB + */ +void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); + +/*! \brief Compute ACK/NACK information for PUSCH/PUCCH for UE transmission in subframe n. This function implements table 10.1-1 of 36.213, p. 69. + @param frame_parms Pointer to DL frame parameter descriptor + @param harq_ack Pointer to dlsch_ue harq_ack status descriptor + @param subframe Subframe for UE transmission (n in 36.213) + @param o_ACK Pointer to ACK/NAK payload for PUCCH/PUSCH + @returns status indicator for PUCCH/PUSCH transmission +*/ +uint8_t nr_get_ack(NR_DL_FRAME_PARMS *frame_parms,nr_harq_status_t *harq_ack,uint8_t subframe_tx,uint8_t subframe_rx,uint8_t *o_ACK, uint8_t cw_idx); + +/*! \brief Reset ACK/NACK information + @param frame_parms Pointer to DL frame parameter descriptor + @param harq_ack Pointer to dlsch_ue harq_ack status descriptor + @param subframe Subframe for UE transmission (n in 36.213) + @param o_ACK Pointer to ACK/NAK payload for PUCCH/PUSCH + @returns status indicator for PUCCH/PUSCH transmission +*/ +uint8_t nr_reset_ack(NR_DL_FRAME_PARMS *frame_parms, + nr_harq_status_t *harq_ack, + unsigned char subframe_tx, + unsigned char subframe_rx, + unsigned char *o_ACK, + uint8_t *pN_bundled, + uint8_t cw_idx); + +/*! \brief Compute UL ACK subframe from DL subframe. This is used to retrieve corresponding DLSCH HARQ pid at eNB upon reception of ACK/NAK information on PUCCH/PUSCH. Derived from Table 10.1-1 in 36.213 (p. 69 in version 8.6) + @param frame_parms Pointer to DL frame parameter descriptor + @param subframe Subframe for UE transmission (n in 36.213) + @param ACK_index TTI bundling index (0,1) + @returns Subframe index for corresponding DL transmission +*/ +uint8_t nr_ul_ACK_subframe2_dl_subframe(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe,uint8_t ACK_index); + +/*! \brief Computes number of DL subframes represented by a particular ACK received on UL (M from Table 10.1-1 in 36.213, p. 69 in version 8.6) + @param frame_parms Pointer to DL frame parameter descriptor + @param subframe Subframe for UE transmission (n in 36.213) + @returns Number of DL subframes (M) +*/ +uint8_t nr_ul_ACK_subframe2_M(NR_DL_FRAME_PARMS *frame_parms,unsigned char subframe); + +/*! \brief Indicates the SR TXOp in current subframe. Implements Table 10.1-5 from 36.213. + @param phy_vars_ue Pointer to UE variables + @param proc Pointer to RXn_TXnp4 thread context + @param eNB_id ID of eNB which is to receive the SR + @returns 1 if TXOp is active. +*/ +uint8_t nr_is_SR_TXOp(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id); + +/*! \brief Gives the UL subframe corresponding to a PDDCH order in subframe n + @param frame_parms Pointer to DL frame parameters + @param proc Pointer to RXn-TXnp4 proc information + @param n subframe of PDCCH + @returns UL subframe corresponding to pdcch order +*/ +uint8_t nr_pdcch_alloc2ul_subframe(NR_DL_FRAME_PARMS *frame_parms,uint8_t n); + +/*! \brief Gives the UL frame corresponding to a PDDCH order in subframe n + @param frame_parms Pointer to DL frame parameters + @param frame Frame of received PDCCH + @param n subframe of PDCCH + @returns UL frame corresponding to pdcch order +*/ +uint32_t nr_pdcch_alloc2ul_frame(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t n); + + +uint16_t nr_get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1); + + +int8_t nr_find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); + +void nr_process_timing_advance(module_id_t Mod_id,uint8_t CC_id,int16_t timing_advance); +void nr_process_timing_advance_rar(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint16_t timing_advance); + +unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb); + +void phy_reset_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index); + +/*! \brief This function retrives the resource (n1_pucch) corresponding to a PDSCH transmission in +subframe n-4 which is acknowledged in subframe n (for FDD) according to n1_pucch = Ncce + N1_pucch. For +TDD, this routine computes the complex procedure described in Section 10.1 of 36.213 (through tables 10.1-1,10.1-2) +@param phy_vars_ue Pointer to UE variables +@param proc Pointer to RXn-TXnp4 proc information +@param harq_ack Pointer to dlsch_ue harq_ack status descriptor +@param eNB_id Index of eNB +@param b Pointer to PUCCH payload (b[0],b[1]) +@param SR 1 means there's a positive SR in parallel to ACK/NAK +@returns n1_pucch +*/ +uint16_t nr_get_n1_pucch(PHY_VARS_NR_UE *phy_vars_ue, + UE_nr_rxtx_proc_t *proc, + nr_harq_status_t *harq_ack, + uint8_t eNB_id, + uint8_t *b, + uint8_t SR); + + +/*! \brief This function retrieves the PHY UE mode. It is used as a helper function for the UE MAC. + @param Mod_id Local UE index on which to act + @param CC_id Component Carrier Index + @param eNB_index ID of eNB + @returns UE mode +*/ +UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); + +/*! \brief This function implements the power control mechanism for PUCCH from 36.213. + @param phy_vars_ue PHY variables + @param proc Pointer to proc descriptor + @param eNB_id Index of eNB + @param pucch_fmt Format of PUCCH that is being transmitted + @returns Transmit power + */ +int16_t nr_pucch_power_cntl(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t subframe,uint8_t eNB_id,PUCCH_FMT_t pucch_fmt); + +/*! \brief This function implements the power control mechanism for PUCCH from 36.213. + @param phy_vars_ue PHY variables + @param proc Pointer to proc descriptor + @param eNB_id Index of eNB + @param j index of type of PUSCH (SPS, Normal, Msg3) + @returns Transmit power + */ +void nr_pusch_power_cntl(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag); + +/*! \brief This function implements the power control mechanism for SRS from 36.213. + @param phy_vars_ue PHY variables + @param proc Pointer to proc descriptor + @param eNB_id Index of eNB + @param j index of type of PUSCH (SPS, Normal, Msg3) + @returns Transmit power + */ +void nr_srs_power_cntl(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t *pnb_rb_srs, uint8_t abstraction_flag); + +void nr_get_cqipmiri_params(PHY_VARS_NR_UE *ue,uint8_t eNB_id); + + + + + + +void nr_dump_dlsch(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid); +void nr_dump_dlsch_SI(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe); +void nr_dump_dlsch_ra(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe); + + +int nr_is_srs_occasion_common(NR_DL_FRAME_PARMS *frame_parms,int frame_tx,int subframe_tx); + +void nr_compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset); + +/*@}*/ + + +#endif + + diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c new file mode 100644 index 0000000000000000000000000000000000000000..58aef566023e01e420991b35499e4bfed581f237 --- /dev/null +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -0,0 +1,6529 @@ +/* + * 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 + */ + +/*! \file phy_procedures_nr_ue.c + * \brief Implementation of UE procedures from 36.213 LTE specifications + * \author R. Knopp, F. Kaltenberger, N. Nikaein, A. Mico Pereperez + * \date 2018 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr + * \note + * \warning + */ + +#define _GNU_SOURCE + +#include "assertions.h" +#include "defs.h" +//#include "PHY/defs.h" +#include "PHY/defs_nr_UE.h" +#include "PHY/phy_vars_nr_ue.h" +//#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" +//#include "PHY/extern.h" +#include "SCHED_NR_UE/defs.h" +#include "SCHED_NR/extern.h" +#include <sched.h> +#include "targets/RT/USER/nr-softmodem.h" + +#ifdef EMOS +#include "SCHED/phy_procedures_emos.h" +#endif + +#define DEBUG_PHY_PROC + +#define NR_PDCCH_SCHED +#define NR_PDCCH_SCHED_DEBUG +#define NR_PUCCH_SCHED +#define NR_PUCCH_SCHED_DEBUG + +#ifndef PUCCH +#define PUCCH +#endif + +#include "LAYER2/NR_MAC_UE/extern.h" +#include "LAYER2/NR_MAC_UE/defs.h" +#include "UTIL/LOG/log.h" + +#ifdef EMOS +fifo_dump_emos_UE emos_dump_UE; +#endif + +#include "UTIL/LOG/vcd_signal_dumper.h" +#include "UTIL/OPT/opt.h" + +#if defined(ENABLE_ITTI) +# include "intertask_interface.h" +#endif + +//#include "PHY/defs.h" + +//#include "PHY/CODING/extern.h" + +#include "T.h" + +#define DLSCH_RB_ALLOC 0x1fbf // skip DC RB (total 23/25 RBs) +#define DLSCH_RB_ALLOC_12 0x0aaa // skip DC RB (total 23/25 RBs) + +#define NS_PER_SLOT 500000 + +extern double cpuf; + + + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) +extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; +#endif + + +#if 0 +void nr_dump_dlsch(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t nr_tti_rx,uint8_t harq_pid) +{ + unsigned int coded_bits_per_codeword; + uint8_t nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; + + coded_bits_per_codeword = get_G(&ue->frame_parms, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[harq_pid]->nb_rb, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[harq_pid]->Qm, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[harq_pid]->Nl, + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, + proc->frame_rx, + nr_tti_rx, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]); + + write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,2,1); + write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_estimates_ext[0],300*nsymb,1,1); + /* + write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); + write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); + write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); + write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); + */ + write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->rxdataF_comp0[0],300*12,1,1); + write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->llr[0],coded_bits_per_codeword,1,0); + + write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_mag0,300*12,1,1); + write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_magb0,300*12,1,1); +} + +void nr_dump_dlsch_SI(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t nr_tti_rx) +{ + unsigned int coded_bits_per_codeword; + uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12); + + coded_bits_per_codeword = get_G(&ue->frame_parms, + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even, + 2, + 1, + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, + proc->frame_rx, + nr_tti_rx, + 0); + LOG_D(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", + ue->Mod_id, + ue->frame_parms.ofdm_symbol_size, + nsymb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, + coded_bits_per_codeword); + + write_output("rxsig0.m","rxs0", &ue->common_vars.rxdata[0][nr_tti_rx*ue->frame_parms.samples_per_tti],ue->frame_parms.samples_per_tti,1,1); + + write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0],nsymb*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_SI[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_SI[0]->dl_ch_estimates_ext[0],ue->frame_parms.N_RB_DL*12*nsymb,1,1); + /* + write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); + write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); + write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); + write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); + */ + write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_SI[0]->rxdataF_comp0[0],ue->frame_parms.N_RB_DL*12*nsymb,1,1); + write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_SI[0]->llr[0],coded_bits_per_codeword,1,0); + + write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_SI[0]->dl_ch_mag0,300*nsymb,1,1); + write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_SI[0]->dl_ch_magb0,300*nsymb,1,1); + sleep(1); + exit(-1); +} + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) +//unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162}; +/* + unsigned int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL) + { + + int gain_dB = power_dBm - power_max_dBm; + int amp_x_100; + + switch (N_RB_UL) { + case 6: + amp_x_100 = AMP; // PRACH is 6 PRBS so no scale + break; + case 15: + amp_x_100 = 158*AMP; // 158 = 100*sqrt(15/6) + break; + case 25: + amp_x_100 = 204*AMP; // 204 = 100*sqrt(25/6) + break; + case 50: + amp_x_100 = 286*AMP; // 286 = 100*sqrt(50/6) + break; + case 75: + amp_x_100 = 354*AMP; // 354 = 100*sqrt(75/6) + break; + case 100: + amp_x_100 = 408*AMP; // 408 = 100*sqrt(100/6) + break; + default: + LOG_E(PHY,"Unknown PRB size %d\n",N_RB_UL); + //mac_xface->macphy_exit(""); + break; + } + if (gain_dB < -30) { + return(amp_x_100/3162); + } else if (gain_dB>0) + return(amp_x_100); + else + return(amp_x_100/gain_table[-gain_dB]); // 245 corresponds to the factor sqrt(25/6) + } +*/ + +unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb) +{ + + int gain_dB = power_dBm - power_max_dBm; + double gain_lin; + + gain_lin = pow(10,.1*gain_dB); + if ((nb_rb >0) && (nb_rb <= N_RB_UL)) { + return((int)(AMP*sqrt(gain_lin*N_RB_UL/(double)nb_rb))); + } + else { + LOG_E(PHY,"Illegal nb_rb/N_RB_UL combination (%d/%d)\n",nb_rb,N_RB_UL); + //mac_xface->macphy_exit(""); + } + return(0); +} + +#endif + +void nr_dump_dlsch_ra(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t nr_tti_rx) +{ + unsigned int coded_bits_per_codeword; + uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12); + + coded_bits_per_codeword = get_G(&ue->frame_parms, + ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even, + 2, + 1, + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, + proc->frame_rx, + nr_tti_rx, + 0); + LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", + ue->Mod_id, + ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_ra[eNB_id]->harq_processes[0]->mcs, + ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, + coded_bits_per_codeword); + + write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0],2*12*ue->frame_parms.ofdm_symbol_size,2,1); + write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_ra[0]->rxdataF_ext[0],2*12*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_ra[0]->dl_ch_estimates_ext[0],300*nsymb,1,1); + /* + write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); + write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); + write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); + write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); + */ + write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_ra[0]->rxdataF_comp0[0],300*nsymb,1,1); + write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_ra[0]->llr[0],coded_bits_per_codeword,1,0); + + write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_ra[0]->dl_ch_mag0,300*nsymb,1,1); + write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_ra[0]->dl_ch_magb0,300*nsymb,1,1); +} + +void phy_reset_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) +{ + + // This flushes ALL DLSCH and ULSCH harq buffers of ALL connected eNBs...add the eNB_index later + // for more flexibility + + uint8_t i,j,k,s; + PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; + + //[NUMBER_OF_RX_THREAD=2][NUMBER_OF_CONNECTED_eNB_MAX][2]; + for(int l=0; l<RX_NB_TH; l++) { + for(i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) { + for(j=0; j<2; j++) { + //DL HARQ + if(ue->dlsch[l][i][j]) { + for(k=0; k<NUMBER_OF_HARQ_PID_MAX && ue->dlsch[l][i][j]->harq_processes[k]; k++) { + ue->dlsch[l][i][j]->harq_processes[k]->status = SCH_IDLE; + for (s=0; s<10; s++) { + // reset ACK/NACK bit to DTX for all nr_tti_rxs s = 0..9 + ue->dlsch[l][i][j]->harq_ack[s].ack = 2; + ue->dlsch[l][i][j]->harq_ack[s].send_harq_status = 0; + ue->dlsch[l][i][j]->harq_ack[s].vDAI_UL = 0xff; + ue->dlsch[l][i][j]->harq_ack[s].vDAI_DL = 0xff; + } + } + } + } + + //UL HARQ + if(ue->ulsch[i]) { + for(k=0; k<NUMBER_OF_HARQ_PID_MAX && ue->ulsch[i]->harq_processes[k]; k++) { + ue->ulsch[i]->harq_processes[k]->status = SCH_IDLE; + //Set NDIs for all UL HARQs to 0 + // ue->ulsch[i]->harq_processes[k]->Ndi = 0; + + } + } + + // flush Msg3 buffer + ue->ulsch_Msg3_active[i] = 0; + + } + } +} + +void ra_failed(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) +{ + + // if contention resolution fails, go back to PRACH + PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PRACH; + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti_is_temporary = 0; + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti = 0; + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti_is_temporary = 0; + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti = 0; + LOG_E(PHY,"[UE %d] Random-access procedure fails, going back to PRACH, setting SIStatus = 0, discard temporary C-RNTI and State RRC_IDLE\n",Mod_id); + //mac_xface->macphy_exit(""); +} + +void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) +{ + + int i; + + LOG_I(PHY,"[UE %d][RAPROC] Random-access procedure succeeded. Set C-RNTI = Temporary C-RNTI\n",Mod_id); + + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti_is_temporary = 0; + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti_is_temporary = 0; + PHY_vars_UE_g[Mod_id][CC_id]->ulsch_Msg3_active[eNB_index] = 0; + PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PUSCH; + + for (i=0; i<8; i++) { + if (PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]) { + PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->status=IDLE; + PHY_vars_UE_g[Mod_id][CC_id]->dlsch[0][eNB_index][0]->harq_processes[i]->round=0; + PHY_vars_UE_g[Mod_id][CC_id]->dlsch[1][eNB_index][0]->harq_processes[i]->round=0; + PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->subframe_scheduling_flag=0; + } + } + + +} + +UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) +{ + + return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index]); + +} +void nr_process_timing_advance_rar(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint16_t timing_advance) { + + ue->timing_advance = timing_advance*4; + + +#ifdef DEBUG_PHY_PROC + /* TODO: fix this log, what is 'HW timing advance'? */ + /*LOG_I(PHY,"[UE %d] AbsoluteSubFrame %d.%d, received (rar) timing_advance %d, HW timing advance %d\n",ue->Mod_id,proc->frame_rx, proc->nr_tti_rx_rx, ue->timing_advance);*/ + LOG_I(PHY,"[UE %d] AbsoluteSubFrame %d.%d, received (rar) timing_advance %d\n",ue->Mod_id,proc->frame_rx, proc->nr_tti_rx, ue->timing_advance); +#endif + +} + +void nr_process_timing_advance(uint8_t Mod_id,uint8_t CC_id,int16_t timing_advance) +{ + + // uint32_t frame = PHY_vars_UE_g[Mod_id]->frame; + + // timing advance has Q1.5 format + timing_advance = timing_advance - 31; + + PHY_vars_UE_g[Mod_id][CC_id]->timing_advance = PHY_vars_UE_g[Mod_id][CC_id]->timing_advance+timing_advance*4; //this is for 25RB only!!! + + + LOG_D(PHY,"[UE %d] Got timing advance %d from MAC, new value %d\n",Mod_id, timing_advance, PHY_vars_UE_g[Mod_id][CC_id]->timing_advance); + + +} + +uint8_t nr_is_SR_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id) +{ + + int nr_tti_tx=proc->nr_tti_tx; + + LOG_D(PHY,"[UE %d][SR %x] Frame %d nr_tti_tx %d Checking for SR TXOp (sr_ConfigIndex %d)\n", + ue->Mod_id,ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->crnti,proc->frame_tx,nr_tti_tx, + ue->scheduling_request_config[eNB_id].sr_ConfigIndex); + + if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 4) { // 5 ms SR period + if ((nr_tti_tx%5) == ue->scheduling_request_config[eNB_id].sr_ConfigIndex) + return(1); + } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 14) { // 10 ms SR period + if (nr_tti_tx==(ue->scheduling_request_config[eNB_id].sr_ConfigIndex-5)) + return(1); + } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 34) { // 20 ms SR period + if ((10*(proc->frame_tx&1)+nr_tti_tx) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15)) + return(1); + } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 74) { // 40 ms SR period + if ((10*(proc->frame_tx&3)+nr_tti_tx) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35)) + return(1); + } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 154) { // 80 ms SR period + if ((10*(proc->frame_tx&7)+nr_tti_tx) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75)) + return(1); + } + + return(0); +} + +uint8_t is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id) +{ + int nr_tti_tx = proc->nr_tti_tx; + int frame = proc->frame_tx; + CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic; + + //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for CQI TXOp (cqi_ConfigIndex %d) isCQIOp %d\n", + // ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,nr_tti_rx, + // cqirep->cqi_PMI_ConfigIndex, + // (((10*frame + nr_tti_tx) % cqirep->Npd) == cqirep->N_OFFSET_CQI)); + + if (cqirep->cqi_PMI_ConfigIndex==-1) + return(0); + else if (((10*frame + nr_tti_tx) % cqirep->Npd) == cqirep->N_OFFSET_CQI) + return(1); + else + return(0); +} +uint8_t is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id) +{ + + + int nr_tti_tx = proc->nr_tti_tx; + int frame = proc->frame_tx; + CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic; + int log2Mri = cqirep->ri_ConfigIndex/161; + int N_OFFSET_RI = cqirep->ri_ConfigIndex % 161; + + //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for RI TXOp (ri_ConfigIndex %d) isRIOp %d\n", + // ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,nr_tti_tx, + // cqirep->ri_ConfigIndex, + // (((10*frame + nr_tti_tx + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0)); + if (cqirep->ri_ConfigIndex==-1) + return(0); + else if (((10*frame + nr_tti_tx + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0) + return(1); + else + return(0); +} + +void compute_cqi_ri_resources(PHY_VARS_NR_UE *ue, + NR_UE_ULSCH_t *ulsch, + uint8_t eNB_id, + uint16_t rnti, + uint16_t p_rnti, + uint16_t cba_rnti, + uint8_t cqi_status, + uint8_t ri_status) +{ + //PHY_MEASUREMENTS *meas = &ue->measurements; + //uint8_t transmission_mode = ue->transmission_mode[eNB_id]; + + + //LOG_I(PHY,"compute_cqi_ri_resources O_RI %d O %d uci format %d \n",ulsch->O_RI,ulsch->O,ulsch->uci_format); + if (cqi_status == 1 || ri_status == 1) + { + ulsch->O = 4; + } +} + +void ue_compute_srs_occasion(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t isSubframeSRS) +{ + + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int frame_tx = proc->frame_tx; + int nr_tti_tx = proc->nr_tti_tx; + SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; + uint16_t srsPeriodicity; + uint16_t srsOffset; + uint8_t is_pucch2_subframe = 0; + uint8_t is_sr_an_subframe = 0; + + // check for SRS opportunity + pSoundingrs_ul_config_dedicated->srsUeSubframe = 0; + pSoundingrs_ul_config_dedicated->srsCellSubframe = isSubframeSRS; + + if (isSubframeSRS) { + LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup); + if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup) + { + nr_compute_srs_pos(frame_parms->frame_type, pSoundingrs_ul_config_dedicated->srs_ConfigIndex, &srsPeriodicity, &srsOffset); + + LOG_D(PHY," srsPeriodicity: %d srsOffset: %d isSubframeSRS %d \n",srsPeriodicity,srsOffset,isSubframeSRS); + + // transmit SRS if the four following constraints are respected: + // - UE is configured to transmit SRS + // - SRS are configured in current nr_tti_rx + // - UE is configured to send SRS in this nr_tti_tx + + // 36.213 8.2 + // 1- A UE shall not transmit SRS whenever SRS and PUCCH format 2/2a/2b transmissions happen to coincide in the same nr_tti_rx + // 2- A UE shall not transmit SRS whenever SRS transmit + // on and PUCCH transmission carrying ACK/NACK and/or + // positive SR happen to coincide in the same nr_tti_rx if the parameter + // Simultaneous-AN-and-SRS is FALSE + + // check PUCCH format 2/2a/2b transmissions + is_pucch2_subframe = is_cqi_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0); + is_pucch2_subframe = (is_ri_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0)) || is_pucch2_subframe; + + // check ACK/SR transmission + if(frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission == FALSE) + { + if(nr_is_SR_TXOp(ue,proc,eNB_id)) + { + uint32_t SR_payload = 0; + if (ue->mac_enabled==1) + { + int Mod_id = ue->Mod_id; + int CC_id = ue->CC_id; + SR_payload = mac_xface->ue_get_SR(Mod_id, + CC_id, + frame_tx, + eNB_id, + ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->crnti, + nr_tti_tx); // nr_tti_tx used for meas gap + + if (SR_payload > 0) + is_sr_an_subframe = 1; + } + } + + uint8_t pucch_ack_payload[2]; + if (nr_get_ack(&ue->frame_parms, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, + nr_tti_tx,proc->nr_tti_rx,pucch_ack_payload,0) > 0) + { + is_sr_an_subframe = 1; + } + } + + // check SRS UE opportunity + if( isSubframeSRS && + (((10*frame_tx+nr_tti_tx) % srsPeriodicity) == srsOffset) + ) + { + if ((is_pucch2_subframe == 0) && (is_sr_an_subframe == 0)) + { + pSoundingrs_ul_config_dedicated->srsUeSubframe = 1; + ue->ulsch[eNB_id]->srs_active = 1; + ue->ulsch[eNB_id]->Nsymb_pusch = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active; + } + else + { + LOG_I(PHY,"DROP UE-SRS-TX for this nr_tti_tx %d.%d: collision with PUCCH2 or SR/AN: PUCCH2-occasion: %d, SR-AN-occasion[simSRS-SR-AN %d]: %d \n", frame_tx, nr_tti_tx, is_pucch2_subframe, frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, is_sr_an_subframe); + } + } + } + LOG_D(PHY," srsCellSubframe: %d, srsUeSubframe: %d, Nsymb-pusch: %d \n", pSoundingrs_ul_config_dedicated->srsCellSubframe, pSoundingrs_ul_config_dedicated->srsUeSubframe, ue->ulsch[eNB_id]->Nsymb_pusch); + } +} + + +void nr_get_cqipmiri_params(PHY_VARS_NR_UE *ue,uint8_t eNB_id) +{ + + CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic; + int cqi_PMI_ConfigIndex = cqirep->cqi_PMI_ConfigIndex; + + if (ue->frame_parms.frame_type == FDD) { + if (cqi_PMI_ConfigIndex <= 1) { // 2 ms CQI_PMI period + cqirep->Npd = 2; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex; + } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period + cqirep->Npd = 5; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-2; + } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period + cqirep->Npd = 10; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-7; + } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period + cqirep->Npd = 20; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-17; + } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period + cqirep->Npd = 40; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-37; + } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period + cqirep->Npd = 80; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-77; + } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period + cqirep->Npd = 160; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-157; + } + else if (cqi_PMI_ConfigIndex > 317) { + + if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period + cqirep->Npd = 32; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-318; + } + else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period + cqirep->Npd = 64; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-350; + } + else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period + cqirep->Npd = 128; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-414; + } + } + } + else { // TDD + if (cqi_PMI_ConfigIndex == 0) { // all UL subframes + cqirep->Npd = 1; + cqirep->N_OFFSET_CQI = 0; + } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period + cqirep->Npd = 5; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-1; + } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period + cqirep->Npd = 10; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-6; + } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period + cqirep->Npd = 20; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-16; + } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period + cqirep->Npd = 40; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-36; + } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period + cqirep->Npd = 80; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-76; + } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period + cqirep->Npd = 160; + cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-156; + } + } +} + +PUCCH_FMT_t get_pucch_format(lte_frame_type_t frame_type, + lte_prefix_type_t cyclic_prefix_type, + uint8_t SR_payload, + uint8_t nb_cw, + uint8_t cqi_status, + uint8_t ri_status, + uint8_t bundling_flag) +{ + if((cqi_status == 0) && (ri_status==0)) + { + // PUCCH Format 1 1a 1b + // 1- SR only ==> PUCCH format 1 + // 2- 1bit Ack/Nack with/without SR ==> PUCCH format 1a + // 3- 2bits Ack/Nack with/without SR ==> PUCCH format 1b + if((nb_cw == 1)&&(bundling_flag==bundling)) + { + return pucch_format1a; + } + if((nb_cw == 1)&&(bundling_flag==multiplexing)) + { + return pucch_format1b; + } + if(nb_cw == 2) + { + return pucch_format1b; + } + if(SR_payload == 1) + { + return pucch_format1; + /* + if (frame_type == FDD) { + return pucch_format1; + } else if (frame_type == TDD) { + return pucch_format1b; + } else { + AssertFatal(1==0,"Unknown frame_type"); + }*/ + } + } + else + { + // PUCCH Format 2 2a 2b + // 1- CQI only or RI only ==> PUCCH format 2 + // 2- CQI or RI + 1bit Ack/Nack for normal CP ==> PUCCH format 2a + // 3- CQI or RI + 2bits Ack/Nack for normal CP ==> PUCCH format 2b + // 4- CQI or RI + Ack/Nack for extended CP ==> PUCCH format 2 + if(nb_cw == 0) + { + return pucch_format2; + } + if(cyclic_prefix_type == NORMAL) + { + if(nb_cw == 1) + { + return pucch_format2a; + } + if(nb_cw == 2) + { + return pucch_format2b; + } + } + else + { + return pucch_format2; + } + } + return pucch_format1a; +} + +uint16_t nr_get_n1_pucch(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + nr_harq_status_t *harq_ack, + uint8_t eNB_id, + uint8_t *b, + uint8_t SR) +{ + + NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + uint8_t nCCE0,nCCE1,nCCE2,nCCE3,harq_ack1,harq_ack0,harq_ack3,harq_ack2; + ANFBmode_t bundling_flag; + uint16_t n1_pucch0=0,n1_pucch1=0,n1_pucch2=0,n1_pucch3=0,n1_pucch_inter; + static uint8_t candidate_dl[9]; // which downlink(s) the current ACK/NACK is associating to + uint8_t last_dl=0xff; // the last downlink with valid DL-DCI. for calculating the PUCCH resource index + int sf; + int M; + uint8_t ack_counter=0; + // clear this, important for case where n1_pucch selection is not used + int nr_tti_tx=proc->nr_tti_tx; + + ue->pucch_sel[nr_tti_tx] = 0; + + if (frame_parms->frame_type == FDD ) { // FDD + sf = (nr_tti_tx<4)? nr_tti_tx+6 : nr_tti_tx-4; + LOG_D(PHY,"n1_pucch_UE: nr_tti_tx %d, nCCE %d\n",sf,ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[sf]); + + if (SR == 0) + return(frame_parms->pucch_config_common.n1PUCCH_AN + ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[sf]); + else + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + } else { + + bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; +#ifdef DEBUG_PHY_PROC + + if (bundling_flag==bundling) { + LOG_D(PHY,"[UE%d] Frame %d nr_tti_tx %d : nr_get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,proc->frame_tx,nr_tti_tx,SR, + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + } else { + LOG_D(PHY,"[UE%d] Frame %d nr_tti_tx %d : nr_get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,proc->frame_tx,nr_tti_tx,SR, + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + } + +#endif + + switch (frame_parms->tdd_config) { + case 1: // DL:S:UL:UL:DL:DL:S:UL:UL:DL + + harq_ack0 = 2; // DTX + M=1; + + // This is the offset for a particular nr_tti_tx (2,3,4) => (0,2,4) + if (nr_tti_tx == 2) { // ACK nr_tti_txs 5,6 + candidate_dl[0] = 6; + candidate_dl[1] = 5; + M=2; + } else if (nr_tti_tx == 3) { // ACK nr_tti_tx 9 + candidate_dl[0] = 9; + } else if (nr_tti_tx == 7) { // ACK nr_tti_txs 0,1 + candidate_dl[0] = 1; + candidate_dl[1] = 0; + M=2; + } else if (nr_tti_tx == 8) { // ACK nr_tti_txs 4 + candidate_dl[0] = 4; + } else { + LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal tx-nr_tti_tx %d for tdd_config %d\n", + ue->Mod_id,proc->frame_tx,nr_tti_tx,frame_parms->tdd_config); + return(0); + } + + // checking which downlink candidate is the last downlink with valid DL-DCI + int k; + for (k=0;k<M;k++) { + if (harq_ack[candidate_dl[k]].send_harq_status>0) { + last_dl = candidate_dl[k]; + break; + } + } + if (last_dl >= 10) { + LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal rx-nr_tti_tx %d (tx-nr_tti_tx %d) for tdd_config %d\n", + ue->Mod_id,proc->frame_tx,last_dl,nr_tti_tx,frame_parms->tdd_config); + return (0); + } + + LOG_D(PHY,"SFN/SF %d/%d calculating n1_pucch0 from last_dl=%d\n", + proc->frame_tx%1024, + proc->nr_tti_tx, + last_dl); + + // i=0 + nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[last_dl]; + n1_pucch0 = nr_get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; + + harq_ack0 = b[0]; + + if (harq_ack0!=2) { // DTX + if (frame_parms->frame_type == FDD ) { + if (SR == 0) { // last paragraph pg 68 from 36.213 (v8.6), m=0 + b[0]=(M==2) ? 1-harq_ack0 : harq_ack0; + b[1]=harq_ack0; // in case we use pucch format 1b (subframes 2,7) + ue->pucch_sel[nr_tti_tx] = 0; + return(n1_pucch0); + } else { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213) + b[0]=harq_ack0; + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + } + } else { + if (SR == 0) { + b[0] = harq_ack0; + b[1] = harq_ack0; + ue->pucch_sel[nr_tti_tx] = 0; + return(n1_pucch0); + } else { + b[0] = harq_ack0; + b[1] = harq_ack0; + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + } + } + } + + + break; + + case 3: // DL:S:UL:UL:UL:DL:DL:DL:DL:DL + // in this configuration we have M=2 from pg 68 of 36.213 (v8.6) + // Note: this doesn't allow using nr_tti_tx 1 for PDSCH transmission!!! (i.e. SF 1 cannot be acked in SF 2) + // set ACK/NAKs to DTX + harq_ack1 = 2; // DTX + harq_ack0 = 2; // DTX + // This is the offset for a particular nr_tti_rx (2,3,4) => (0,2,4) + last_dl = (nr_tti_tx-2)<<1; + // i=0 + nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[5+last_dl]; + n1_pucch0 = nr_get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=1 + nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(6+last_dl)%10]; + n1_pucch1 = nr_get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; + + // set ACK/NAK to values if not DTX + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(6+last_dl)%10].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed + harq_ack1 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(6+last_dl)%10].ack; + + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[5+last_dl].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed + harq_ack0 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[5+last_dl].ack; + + LOG_D(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d cce1=%d n1_pucch1=%d\n", + proc->frame_tx%1024, + proc->nr_tti_tx, + nCCE0,n1_pucch0, + nCCE1,n1_pucch1); + + if (harq_ack1!=2) { // n-6 // nr_tti_tx 6,8,0 and maybe 5,7,9 is to be ACK/NAKed + + if ((bundling_flag==bundling)&&(SR == 0)) { // This is for bundling without SR, + // n1_pucch index takes value of smallest element in set {0,1} + // i.e. 0 if harq_ack0 is not DTX, otherwise 1 + b[0] = harq_ack1; + + if (harq_ack0!=2) + b[0]=b[0]&harq_ack0; + + ue->pucch_sel[nr_tti_tx] = 1; + return(n1_pucch1); + + } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 + if (harq_ack0 == 2) + harq_ack0 = 0; + + b[1] = harq_ack0; + b[0] = (harq_ack0!=harq_ack1)?0:1; + + if ((harq_ack0 == 1) && (harq_ack1 == 0)) { + ue->pucch_sel[nr_tti_tx] = 0; + return(n1_pucch0); + } else { + ue->pucch_sel[nr_tti_tx] = 1; + return(n1_pucch1); + } + } else if (SR==1) { // SR and 0,1,or 2 ACKS, (first 3 entries in Table 7.3-1 of 36.213) + // this should be number of ACKs (including + if (harq_ack0 == 2) + harq_ack0 = 0; + + b[0]= harq_ack1 | harq_ack0; + b[1]= harq_ack1 ^ harq_ack0; + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + } + } else if (harq_ack0!=2) { // n-7 // nr_tti_tx 5,7,9 only is to be ACK/NAKed + if ((bundling_flag==bundling)&&(SR == 0)) { // last paragraph pg 68 from 36.213 (v8.6), m=0 + b[0]=harq_ack0; + ue->pucch_sel[nr_tti_tx] = 0; + return(n1_pucch0); + } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 with i=1 set to DTX + b[0] = harq_ack0; + b[1] = 1-b[0]; + ue->pucch_sel[nr_tti_tx] = 0; + return(n1_pucch0); + } else if (SR==1) { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213) + b[0]=harq_ack0; + b[1]=b[0]; + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + } + } + + break; + + case 4: // DL:S:UL:UL:DL:DL:DL:DL:DL:DL + // in this configuration we have M=4 from pg 68 of 36.213 (v8.6) + // Note: this doesn't allow using nr_tti_tx 1 for PDSCH transmission!!! (i.e. SF 1 cannot be acked in SF 2) + // set ACK/NAKs to DTX + harq_ack3 = 2; // DTX + harq_ack2 = 2; // DTX + harq_ack1 = 2; // DTX + harq_ack0 = 2; // DTX + // This is the offset for a particular nr_tti_tx (2,3,4) => (0,2,4) + //last_dl = (nr_tti_tx-2)<<1; + if (nr_tti_tx == 2) { + // i=0 + //nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[2+nr_tti_tx]; + nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(8+nr_tti_tx)%10]; + n1_pucch0 = 2*nr_get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=1 + nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[2+nr_tti_tx]; + n1_pucch1 = nr_get_Np(frame_parms->N_RB_DL,nCCE1,0) + nr_get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; + // i=2 + nCCE2 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(8+nr_tti_tx)%10]; + + n1_pucch2 = 2*nr_get_Np(frame_parms->N_RB_DL,nCCE2,1) + nCCE2+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=3 + //nCCE3 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(9+nr_tti_tx)%10]; + //n1_pucch3 = nr_get_Np(frame_parms->N_RB_DL,nCCE3,1) + nCCE3 + frame_parms->pucch_config_common.n1PUCCH_AN; + + // set ACK/NAK to values if not DTX + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(8+nr_tti_tx)%10].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed + harq_ack0 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(8+nr_tti_tx)%10].ack; + + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[2+nr_tti_tx].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed + harq_ack1 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[2+nr_tti_tx].ack; + + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[3+nr_tti_tx].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed + harq_ack2 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[3+nr_tti_tx].ack; + + //if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(9+nr_tti_tx)%10].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed + //harq_ack3 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(9+nr_tti_tx)%10].ack; + //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d cce1=%d n1_pucch1=%d cce2=%d n1_pucch2=%d\n", + // proc->frame_tx%1024, + // proc->nr_tti_tx_tx, + // nCCE0,n1_pucch0, + // nCCE1,n1_pucch1, nCCE2, n1_pucch2); + }else if (nr_tti_tx == 3) { + // i=0 + + nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[4+nr_tti_tx]; + n1_pucch0 = 3*nr_get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=1 + nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[5+nr_tti_tx]; + n1_pucch1 = 2*nr_get_Np(frame_parms->N_RB_DL,nCCE1,0) + nr_get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; + // i=2 + nCCE2 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(6+nr_tti_tx)]; + n1_pucch2 = nr_get_Np(frame_parms->N_RB_DL,nCCE2,0) + 2*nr_get_Np(frame_parms->N_RB_DL,nCCE2,1) + nCCE2+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=3 + nCCE3 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(3+nr_tti_tx)]; + n1_pucch3 = 3*nr_get_Np(frame_parms->N_RB_DL,nCCE3,1) + nCCE3 + frame_parms->pucch_config_common.n1PUCCH_AN; + + // set ACK/NAK to values if not DTX + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[4+nr_tti_tx].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed + harq_ack0 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[4+nr_tti_tx].ack; + + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[5+nr_tti_tx].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed + harq_ack1 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[5+nr_tti_tx].ack; + + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(6+nr_tti_tx)].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed + harq_ack2 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(6+nr_tti_tx)].ack; + + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(3+nr_tti_tx)].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed + harq_ack3 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(3+nr_tti_tx)].ack; + } + + //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d harq_ack0=%d cce1=%d n1_pucch1=%d harq_ack1=%d cce2=%d n1_pucch2=%d harq_ack2=%d cce3=%d n1_pucch3=%d harq_ack3=%d bundling_flag=%d\n", + // proc->frame_tx%1024, + // proc->nr_tti_tx, + // nCCE0,n1_pucch0,harq_ack0, + // nCCE1,n1_pucch1,harq_ack1, nCCE2, n1_pucch2, harq_ack2, + // nCCE3, n1_pucch3, harq_ack3, bundling_flag); + + if ((bundling_flag==bundling)&&(SR == 0)) { // This is for bundling without SR, + b[0] = 1; + ack_counter = 0; + + if ((harq_ack3!=2) ) { + b[0] = b[0]&harq_ack3; + n1_pucch_inter = n1_pucch3; + ack_counter ++; + } + if ((harq_ack0!=2) ) { + b[0] = b[0]&harq_ack0; + n1_pucch_inter = n1_pucch0; + ack_counter ++; + } + if ((harq_ack1!=2) ) { + b[0] = b[0]&harq_ack1; + n1_pucch_inter = n1_pucch1; + ack_counter ++; + } + if ((harq_ack2!=2) ) { + b[0] = b[0]&harq_ack2; + n1_pucch_inter = n1_pucch2; + ack_counter ++; + } + + if (ack_counter == 0) + b[0] = 0; + + /*if (nr_tti_tx == 3) { + n1_pucch_inter = n1_pucch2; + } else if (nr_tti_tx == 2) { + n1_pucch_inter = n1_pucch1; + }*/ + + //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch n1_pucch_inter=%d b[0]=%d b[1]=%d \n", + // proc->frame_tx%1024, + // proc->nr_tti_tx,n1_pucch_inter, + // b[0],b[1]); + + return(n1_pucch_inter); + + } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 + + if (nr_tti_tx == 3) { + LOG_I(PHY, "sbuframe=%d \n",nr_tti_tx); + if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) { + b[0] = 1; + b[1] = 1; + return(n1_pucch1); + } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { + b[0] = 1; + b[1] = 0; + return(n1_pucch1); + } else if (((harq_ack0 == 0) || (harq_ack0 == 2)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 0) && (harq_ack3 == 2)) { + b[0] = 1; + b[1] = 1; + return(n1_pucch2); + } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) { + b[0] = 1; + b[1] = 0; + return(n1_pucch1); + } else if ((harq_ack0 == 0) && (harq_ack1 == 2) && (harq_ack2 == 2) && (harq_ack3 == 2)) { + b[0] = 1; + b[1] = 0; + return(n1_pucch0); + } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { + b[0] = 1; + b[1] = 0; + return(n1_pucch1); + } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && (harq_ack3 == 1)) { + b[0] = 0; + b[1] = 1; + return(n1_pucch3); + } else if (((harq_ack0 == 0) || (harq_ack0 == 2)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 0)) { + b[0] = 1; + b[1] = 1; + return(n1_pucch3); + } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { + b[0] = 0; + b[1] = 1; + return(n1_pucch2); + } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) { + b[0] = 0; + b[1] = 1; + return(n1_pucch0); + } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { + b[0] = 0; + b[1] = 1; + return(n1_pucch0); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) { + b[0] = 0; + b[1] = 1; + return(n1_pucch3); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 0) && (harq_ack2 == 2) && (harq_ack3 == 2)) { + b[0] = 0; + b[1] = 0; + return(n1_pucch1); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { + b[0] = 1; + b[1] = 0; + return(n1_pucch2); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) { + b[0] = 1; + b[1] = 0; + return(n1_pucch3); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { + b[0] = 0; + b[1] = 1; + return(n1_pucch1); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && (harq_ack3 == 1)) { + b[0] = 0; + b[1] = 1; + return(n1_pucch3); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { + b[0] = 0; + b[1] = 0; + return(n1_pucch2); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack3 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { + b[0] = 0; + b[1] = 0; + return(n1_pucch3); + } + } else if (nr_tti_tx == 2) { + if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1)) { + b[0] = 1; + b[1] = 1; + return(n1_pucch2); + } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { + b[0] = 1; + b[1] = 1; + return(n1_pucch1); + } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1)) { + b[0] = 1; + b[1] = 1; + return(n1_pucch0); + } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { + b[0] = 0; + b[1] = 1; + return(n1_pucch0); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1)) { + b[0] = 1; + b[1] = 0; + return(n1_pucch2); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { + b[1] = 0; + b[0] = 0; + return(n1_pucch1); + } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1)) { + b[0] = 0; + b[1] = 0; + return(n1_pucch2); + } else if ((harq_ack0 == 2) && (harq_ack1 == 2) && (harq_ack2 == 0)) { + b[0] = 0; + b[1] = 1; + return(n1_pucch2); + } else if ((harq_ack0 == 2) && (harq_ack1 == 0) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { + b[0] = 1; + b[1] = 0; + return(n1_pucch1); + } else if ((harq_ack0 == 0) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { + b[0] = 1; + b[1] = 0; + return(n1_pucch0); + } + + } + } else if (SR==1) { // SR and 0,1,or 2 ACKS, (first 3 entries in Table 7.3-1 of 36.213) + // this should be number of ACKs (including + ack_counter = 0; + if (harq_ack0==1) + ack_counter ++; + if (harq_ack1==1) + ack_counter ++; + if (harq_ack2==1) + ack_counter ++; + if (harq_ack3==1) + ack_counter ++; + + switch (ack_counter) { + case 0: + b[0] = 0; + b[1] = 0; + break; + + case 1: + b[0] = 1; + b[1] = 1; + break; + + case 2: + b[0] = 1; + b[1] = 0; + break; + + case 3: + b[0] = 0; + b[1] = 1; + break; + + case 4: + b[0] = 1; + b[1] = 1; + break; + } + + ack_counter = 0; + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + } + + break; + + } // switch tdd_config + } + + LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, exit without proper return\n", ue->Mod_id, proc->frame_tx); + return(-1); +} + + +#ifdef EMOS + + void phy_procedures_emos_UE_TX(uint8_t next_slot,uint8_t eNB_id) { + uint8_t harq_pid; + + + if (next_slot%2==0) { + // get harq_pid from nr_tti_tx relationship + harq_pid = nr_subframe2harq_pid(&ue->frame_parms,ue->frame,(next_slot>>1)); + if (harq_pid==255) { + LOG_E(PHY,"[UE%d] Frame %d : FATAL ERROR: illegal harq_pid, returning\n", + 0,ue->frame); + return; + } + + if (ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { + emos_dump_UE.uci_cnt[next_slot>>1] = 1; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o,ulsch[eNB_id]->o,MAX_CQI_BITS*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O = ulsch[eNB_id]->O; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_RI,ulsch[eNB_id]->o_RI,2*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O_RI = ulsch[eNB_id]->O_RI; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_ACK,ulsch[eNB_id]->o_ACK,4*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O_ACK = ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK; + } + else { + emos_dump_UE.uci_cnt[next_slot>>1] = 0; + } + } + } + +#endif + +void ulsch_common_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t empty_subframe) { + + int aa; + NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + + int nsymb; + int nr_tti_tx = proc->nr_tti_tx; + int frame_tx = proc->frame_tx; + int ulsch_start; + int overflow=0; +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + int k,l; + int dummy_tx_buffer[frame_parms->samples_per_subframe] __attribute__((aligned(16))); +#endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN); +#if UE_TIMING_TRACE + start_meas(&ue->ofdm_mod_stats); +#endif + nsymb = (frame_parms->Ncp == 0) ? 14 : 12; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)//this is the EXPRESS MIMO case + ulsch_start = (ue->rx_offset+nr_tti_tx*frame_parms->samples_per_subframe- + ue->hw_timing_advance- + ue->timing_advance- + ue->N_TA_offset+5); + //LOG_E(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d]\n",nr_tti_tx, ulsch_start); + + if(ulsch_start < 0) + ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); + + if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe)) + ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); + + //LOG_E(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d]\n",nr_tti_tx, ulsch_start); +#else //this is the normal case + ulsch_start = (frame_parms->samples_per_subframe*nr_tti_tx)-ue->N_TA_offset; //-ue->timing_advance; +#endif //else EXMIMO + +//#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + if (empty_subframe) + { +//#if 1 + overflow = ulsch_start - 9*frame_parms->samples_per_subframe; + for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { + + if (overflow > 0) + { + memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*(frame_parms->samples_per_subframe-overflow)); + memset(&ue->common_vars.txdata[aa][0],0,4*overflow); + } + else + { + memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*frame_parms->samples_per_subframe); + } + } +/*#else + overflow = ulsch_start - 9*frame_parms->samples_per_subframe; + for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { + for (k=ulsch_start; k<cmin(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_subframe); k++) { + ((short*)ue->common_vars.txdata[aa])[2*k] = 0; + ((short*)ue->common_vars.txdata[aa])[2*k+1] = 0; + } + + for (k=0; k<overflow; k++) { + ((short*)ue->common_vars.txdata[aa])[2*k] = 0; + ((short*)ue->common_vars.txdata[aa])[2*k+1] = 0; + } + } +endif*/ + return; + } + + + if ((frame_tx%100) == 0) + LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: ulsch_start = %d (rxoff %d, HW TA %d, timing advance %d, TA_offset %d\n", + ue->Mod_id,frame_tx,nr_tti_tx, + ulsch_start, + ue->rx_offset, + ue->hw_timing_advance, + ue->timing_advance, + ue->N_TA_offset); + + + for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { + if (frame_parms->Ncp == 1) + PHY_ofdm_mod(&ue->common_vars.txdataF[aa][nr_tti_tx*nsymb*frame_parms->ofdm_symbol_size], +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + dummy_tx_buffer, +#else + &ue->common_vars.txdata[aa][ulsch_start], +#endif + frame_parms->ofdm_symbol_size, + nsymb, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + else + normal_prefix_mod(&ue->common_vars.txdataF[aa][nr_tti_tx*nsymb*frame_parms->ofdm_symbol_size], +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + dummy_tx_buffer, +#else + &ue->common_vars.txdata[aa][ulsch_start], +#endif + nsymb, + &ue->frame_parms); + + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + apply_7_5_kHz(ue,dummy_tx_buffer,0); + apply_7_5_kHz(ue,dummy_tx_buffer,1); +#else + apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],0); + apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],1); +#endif + + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + overflow = ulsch_start - 9*frame_parms->samples_per_subframe; + + + for (k=ulsch_start,l=0; k<cmin(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_subframe); k++,l++) { + ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; + ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; + } + + for (k=0; k<overflow; k++,l++) { + ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; + ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; + } +#if defined(EXMIMO) + // handle switch before 1st TX nr_tti_rx, guarantee that the slot prior to transmission is switch on + for (k=ulsch_start - (frame_parms->samples_per_subframe>>1) ; k<ulsch_start ; k++) { + if (k<0) + ue->common_vars.txdata[aa][k+frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; + else if (k>(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) + ue->common_vars.txdata[aa][k-frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; + else + ue->common_vars.txdata[aa][k] &= 0xFFFEFFFE; + } +#endif +#endif + /* + only for debug + LOG_I(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d, TA: %d, rxOffset: %d, timing_advance: %d, hw_timing_advance: %d]\n",nr_tti_tx, ulsch_start, ue->N_TA_offset, ue->rx_offset, ue->timing_advance, ue->hw_timing_advance); + if( (crash == 1) && (nr_tti_tx == 0) ) + { + LOG_E(PHY,"***** DUMP TX Signal [ulsch_start %d] *****\n",ulsch_start); + write_output("txBuff.m","txSignal",&ue->common_vars.txdata[aa][ulsch_start],frame_parms->samples_per_subframe,1,1); + } + */ + + } //nb_antennas_tx + +#if UE_TIMING_TRACE + stop_meas(&ue->ofdm_mod_stats); +#endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_OUT); + +} + +void ue_prach_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode) { + + int frame_tx = proc->frame_tx; + int nr_tti_tx = proc->nr_tti_tx; + int prach_power; + PRACH_RESOURCES_t prach_resources_local; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN); + + ue->generate_prach=0; + + if (ue->mac_enabled==0){ + ue->prach_resources[eNB_id] = &prach_resources_local; + prach_resources_local.ra_RNTI = 0xbeef; + prach_resources_local.ra_PreambleIndex = 0; + } + + if (ue->mac_enabled==1){ + // ask L2 for RACH transport + if ((mode != rx_calib_ue) && (mode != rx_calib_ue_med) && (mode != rx_calib_ue_byp) && (mode != no_L2_connect) ) { + LOG_D(PHY,"Getting PRACH resources\n"); + //ue->prach_resources[eNB_id] = mac_xface->ue_get_rach(ue->Mod_id, + ue->CC_id, + frame_tx, + eNB_id, + nr_tti_tx); + LOG_D(PHY,"Got prach_resources for eNB %d address %p, RRCCommon %p\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[ue->Mod_id].radioResourceConfigCommon); + LOG_D(PHY,"Prach resources %p\n",ue->prach_resources[eNB_id]); + } + } + + if (ue->prach_resources[eNB_id]!=NULL) { + + ue->generate_prach=1; + ue->prach_cnt=0; +#ifdef SMBV + ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; +#endif +#ifdef OAI_EMU + ue->prach_PreambleIndex=ue->prach_resources[eNB_id]->ra_PreambleIndex; +#endif + + if (abstraction_flag == 0) { + + LOG_I(PHY,"mode %d\n",mode); + + if ((ue->mac_enabled==1) && (mode != calib_prach_tx)) { + ue->tx_power_dBm[nr_tti_tx] = ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(ue->Mod_id,ue->CC_id,eNB_id); + } + else { + ue->tx_power_dBm[nr_tti_tx] = ue->tx_power_max_dBm; + ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; + } + + LOG_I(PHY,"[UE %d][RAPROC] Frame %d, nr_tti_rx %d : Generating PRACH, preamble %d,PL %d, P0_PRACH %d, TARGET_RECEIVED_POWER %d dBm, PRACH TDD Resource index %d, RA-RNTI %d\n", + ue->Mod_id, + frame_tx, + nr_tti_tx, + ue->prach_resources[eNB_id]->ra_PreambleIndex, + get_PL(ue->Mod_id,ue->CC_id,eNB_id), + ue->tx_power_dBm[nr_tti_tx], + ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER, + ue->prach_resources[eNB_id]->ra_TDD_map_index, + ue->prach_resources[eNB_id]->ra_RNTI); + + ue->tx_total_RE[nr_tti_tx] = 96; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm[nr_tti_tx], + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + 6); +#else + ue->prach_vars[eNB_id]->amp = AMP; +#endif + if ((mode == calib_prach_tx) && (((proc->frame_tx&0xfffe)%100)==0)) + LOG_D(PHY,"[UE %d][RAPROC] Frame %d, nr_tti_rx %d : PRACH TX power %d dBm, amp %d\n", + ue->Mod_id, + proc->frame_rx, + proc->nr_tti_tx, + ue->tx_power_dBm[nr_tti_tx], + ue->prach_vars[eNB_id]->amp); + + + // start_meas(&ue->tx_prach); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_IN); + prach_power = generate_prach(ue,eNB_id,nr_tti_tx,frame_tx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_OUT); + // stop_meas(&ue->tx_prach); + LOG_D(PHY,"[UE %d][RAPROC] PRACH PL %d dB, power %d dBm, digital power %d dB (amp %d)\n", + ue->Mod_id, + get_PL(ue->Mod_id,ue->CC_id,eNB_id), + ue->tx_power_dBm[nr_tti_tx], + dB_fixed(prach_power), + ue->prach_vars[eNB_id]->amp); + } else { + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.prach_flag=1; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.prach_id=ue->prach_resources[eNB_id]->ra_PreambleIndex; + } + + if (ue->mac_enabled==1){ + //mac_xface->Msg1_transmitted(ue->Mod_id, + ue->CC_id, + frame_tx, + eNB_id); + } + + LOG_I(PHY,"[UE %d][RAPROC] Frame %d, nr_tti_rx %d: Generating PRACH (eNB %d) preamble index %d for UL, TX power %d dBm (PL %d dB), l3msg \n", + ue->Mod_id,frame_tx,nr_tti_tx,eNB_id, + ue->prach_resources[eNB_id]->ra_PreambleIndex, + ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(ue->Mod_id,ue->CC_id,eNB_id), + get_PL(ue->Mod_id,ue->CC_id,eNB_id)); + + } + + + // if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue + if (mode == calib_prach_tx) + ue->prach_resources[eNB_id]=NULL; + + LOG_D(PHY,"[UE %d] frame %d nr_tti_rx %d : generate_prach %d, prach_cnt %d\n", + ue->Mod_id,frame_tx,nr_tti_tx,ue->generate_prach,ue->prach_cnt); + + ue->prach_cnt++; + + if (ue->prach_cnt==3) + ue->generate_prach=0; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_OUT); +} + +void ue_ulsch_uespec_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) { + + int harq_pid; + int frame_tx=proc->frame_tx; + int nr_tti_tx=proc->nr_tti_tx; + int Mod_id = ue->Mod_id; + int CC_id = ue->CC_id; + uint8_t Msg3_flag=0; + uint16_t first_rb, nb_rb; + unsigned int input_buffer_length; + int i; + int aa; + int tx_amp; + uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32))); + uint8_t access_mode; + uint8_t Nbundled=0; + uint8_t NbundledCw1=0; + uint8_t ack_status_cw0=0; + uint8_t ack_status_cw1=0; + uint8_t cqi_status = 0; + uint8_t ri_status = 0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_IN); + + // get harq_pid from nr_tti_rx relationship + harq_pid = nr_subframe2harq_pid(&ue->frame_parms, + frame_tx, + nr_tti_tx); + + + if (ue->mac_enabled == 1) { + if ((ue->ulsch_Msg3_active[eNB_id] == 1) && + (ue->ulsch_Msg3_frame[eNB_id] == frame_tx) && + (ue->ulsch_Msg3_subframe[eNB_id] == nr_tti_tx)) { // Initial Transmission of Msg3 + + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) + generate_ue_ulsch_params_from_rar(ue, + proc, + eNB_id); + + ue->ulsch[eNB_id]->power_offset = 14; + LOG_D(PHY,"[UE %d][RAPROC] Frame %d: Setting Msg3_flag in nr_tti_rx %d, for harq_pid %d\n", + Mod_id, + frame_tx, + nr_tti_tx, + harq_pid); + Msg3_flag = 1; + } else { + + if (harq_pid==255) { + LOG_E(PHY,"[UE%d] Frame %d nr_tti_rx %d ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n", + Mod_id,frame_tx, nr_tti_tx); + //mac_xface->macphy_exit("Error in ulsch_decoding"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&ue->phy_proc_tx); +#endif + return; + } + + Msg3_flag=0; + } + } + + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { + + uint8_t isBad = 0; + if (ue->frame_parms.N_RB_UL <= ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb) { + LOG_D(PHY,"Invalid PUSCH first_RB=%d for N_RB_UL=%d\n", + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, + ue->frame_parms.N_RB_UL); + isBad = 1; + } + if (ue->frame_parms.N_RB_UL < ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb) { + LOG_D(PHY,"Invalid PUSCH num_RB=%d for N_RB_UL=%d\n", + ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, + ue->frame_parms.N_RB_UL); + isBad = 1; + } + if (0 > ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb) { + LOG_D(PHY,"Invalid PUSCH first_RB=%d\n", + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb); + isBad = 1; + } + if (0 >= ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb) { + LOG_D(PHY,"Invalid PUSCH num_RB=%d\n", + ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb); + isBad = 1; + } + if (ue->frame_parms.N_RB_UL < (ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb)) { + LOG_D(PHY,"Invalid PUSCH num_RB=%d + first_RB=%d for N_RB_UL=%d\n", + ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, + ue->frame_parms.N_RB_UL); + isBad = 1; + } + if ((0 > ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx) || + (3 < ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx)) { + LOG_D(PHY,"Invalid PUSCH RV index=%d\n", ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx); + isBad = 1; + } + + if (20 < ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs) { + LOG_D(PHY,"Not supported MCS in OAI mcs=%d\n", ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs); + isBad = 1; + } + + if (isBad) { + LOG_I(PHY,"Skip PUSCH generation!\n"); + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; + } + } + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { + + ue->generate_ul_signal[eNB_id] = 1; + + // deactivate service request + // ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; + LOG_D(PHY,"Generating PUSCH (Abssubframe: %d.%d): harq-Id: %d, round: %d, MaxReTrans: %d \n",frame_tx,nr_tti_tx,harq_pid,ue->ulsch[eNB_id]->harq_processes[harq_pid]->round,ue->ulsch[eNB_id]->Mlimit); + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round >= (ue->ulsch[eNB_id]->Mlimit - 1)) + { + LOG_D(PHY,"PUSCH MAX Retransmission achieved ==> send last pusch\n"); + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; + } + + ack_status_cw0 = nr_reset_ack(&ue->frame_parms, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, + nr_tti_tx, + proc->nr_tti_rx, + ue->ulsch[eNB_id]->o_ACK, + &Nbundled, + 0); + ack_status_cw1 = nr_reset_ack(&ue->frame_parms, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][1]->harq_ack, + nr_tti_tx, + proc->nr_tti_rx, + ue->ulsch[eNB_id]->o_ACK, + &NbundledCw1, + 1); + + //Nbundled = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack; + //ue->ulsch[eNB_id]->bundling = Nbundled; + + first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; + nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; + + + // check Periodic CQI/RI reporting + cqi_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0)&& + (is_cqi_TXOp(ue,proc,eNB_id)==1)); + + ri_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) && + (is_ri_TXOp(ue,proc,eNB_id)==1)); + + // compute CQI/RI resources + compute_cqi_ri_resources(ue, ue->ulsch[eNB_id], eNB_id, ue->ulsch[eNB_id]->rnti, P_RNTI, CBA_RNTI, cqi_status, ri_status); + + if (ack_status_cw0 > 0) { + + // check if we received a PDSCH at nr_tti_tx - 4 + // ==> send ACK/NACK on PUSCH + if (ue->frame_parms.frame_type == FDD) + { + ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK = ack_status_cw0 + ack_status_cw1; + } + + +#if T_TRACER + if(ue->ulsch[eNB_id]->o_ACK[0]) + { + LOG_I(PHY,"PUSCH ACK\n"); + T(T_UE_PHY_DLSCH_UE_ACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx), T_INT(Mod_id), T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti), + T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->current_harq_pid)); + } + else + { + LOG_I(PHY,"PUSCH NACK\n"); + T(T_UE_PHY_DLSCH_UE_NACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx), T_INT(Mod_id), T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti), + T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->current_harq_pid)); + } +#endif +#ifdef UE_DEBUG_TRACE + LOG_I(PHY,"[UE %d][PDSCH %x] AbsSubFrame %d.%d Generating ACK (%d,%d) for %d bits on PUSCH\n", + Mod_id, + ue->ulsch[eNB_id]->rnti, + frame_tx%1024,nr_tti_tx, + ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK); +#endif + } + + //#ifdef UE_DEBUG_TRACE + LOG_I(PHY, + "[UE %d][PUSCH %d] AbsSubframe %d.%d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, tbs %d, rv %d, " + "cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d, ack_status_cw0 %d ack_status_cw1 %d bundling %d, Nbundled %d, CQI %d, RI %d\n", + Mod_id,harq_pid,frame_tx%1024,nr_tti_tx, + first_rb,nb_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, + (ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift+ + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2+ + ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[nr_tti_tx<<1])%12, + ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2, + ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[nr_tti_tx<<1], + ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK, + ack_status_cw0, + ack_status_cw1, + ue->ulsch[eNB_id]->bundling, Nbundled, + cqi_status, + ri_status); + //#endif + + + + + + if (Msg3_flag == 1) { + LOG_I(PHY,"[UE %d][RAPROC] Frame %d, nr_tti_rx %d Generating (RRCConnectionRequest) Msg3 (nb_rb %d, first_rb %d, round %d, rvidx %d) Msg3: %x.%x.%x|%x.%x.%x.%x.%x.%x\n",Mod_id,frame_tx, + nr_tti_tx, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, + ue->prach_resources[eNB_id]->Msg3[0], + ue->prach_resources[eNB_id]->Msg3[1], + ue->prach_resources[eNB_id]->Msg3[2], + ue->prach_resources[eNB_id]->Msg3[3], + ue->prach_resources[eNB_id]->Msg3[4], + ue->prach_resources[eNB_id]->Msg3[5], + ue->prach_resources[eNB_id]->Msg3[6], + ue->prach_resources[eNB_id]->Msg3[7], + ue->prach_resources[eNB_id]->Msg3[8]); +#if UE_TIMING_TRACE + start_meas(&ue->ulsch_encoding_stats); +#endif + + if (abstraction_flag==0) { + if (ulsch_encoding(ue->prach_resources[eNB_id]->Msg3, + ue, + harq_pid, + eNB_id, + proc->nr_tti_rx, + ue->transmission_mode[eNB_id],0,0)!=0) { + LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); + //mac_xface->macphy_exit("Error in ulsch_coding"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&ue->phy_proc_tx); + printf("------FULL TX PROC : %5.2f ------\n",ue->phy_proc_tx.p_time/(cpuf*1000.0)); +#endif + return; + } + } + +#ifdef PHY_ABSTRACTION + else { + ulsch_encoding_emul(ue->prach_resources[eNB_id]->Msg3,ue,eNB_id,proc->nr_tti_rx,harq_pid,0); + } + +#endif + +#if UE_TIMING_TRACE + stop_meas(&ue->ulsch_encoding_stats); +#endif + if (ue->mac_enabled == 1) { + // signal MAC that Msg3 was sent + //mac_xface->Msg3_transmitted(Mod_id, + CC_id, + frame_tx, + eNB_id); + } + } // Msg3_flag==1 + else { + input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; + + if (ue->mac_enabled==1) { + // LOG_D(PHY,"[UE %d] ULSCH : Searching for MAC SDUs\n",Mod_id); + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) { + //if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { + access_mode=SCHEDULED_ACCESS; + //mac_xface->ue_get_sdu(Mod_id, + CC_id, + frame_tx, + proc->subframe_tx, + nr_tti_tx%(ue->frame_parms.ttis_per_subframe), + eNB_id, + ulsch_input_buffer, + input_buffer_length, + &access_mode); + } + +#ifdef DEBUG_PHY_PROC +#ifdef DEBUG_ULSCH + LOG_D(PHY,"[UE] Frame %d, nr_tti_rx %d : ULSCH SDU (TX harq_pid %d) (%d bytes) : \n",frame_tx,nr_tti_tx,harq_pid, ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3); + + for (i=0; i<ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3; i++) + LOG_T(PHY,"%x.",ulsch_input_buffer[i]); + + LOG_T(PHY,"\n"); +#endif +#endif + } + else { + unsigned int taus(void); + + for (i=0; i<input_buffer_length; i++) + ulsch_input_buffer[i]= (uint8_t)(taus()&0xff); + + } + +#if UE_TIMING_TRACE + start_meas(&ue->ulsch_encoding_stats); +#endif + if (abstraction_flag==0) { + + if (ulsch_encoding(ulsch_input_buffer, + ue, + harq_pid, + eNB_id, + proc->nr_tti_rx, + ue->transmission_mode[eNB_id],0, + Nbundled)!=0) { + LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&ue->phy_proc_tx); +#endif + return; + } + } + +#ifdef PHY_ABSTRACTION + else { + ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,proc->nr_tti_rx,harq_pid,0); + } + +#endif +#if UE_TIMING_TRACE + stop_meas(&ue->ulsch_encoding_stats); +#endif + } + + if (abstraction_flag == 0) { + if (ue->mac_enabled==1) { + nr_pusch_power_cntl(ue,proc,eNB_id,1, abstraction_flag); + ue->tx_power_dBm[nr_tti_tx] = ue->ulsch[eNB_id]->Po_PUSCH; + } + else { + ue->tx_power_dBm[nr_tti_tx] = ue->tx_power_max_dBm; + } + ue->tx_total_RE[nr_tti_tx] = nb_rb*12; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + tx_amp = get_tx_amp(ue->tx_power_dBm[nr_tti_tx], + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + nb_rb); +#else + tx_amp = AMP; +#endif +#if T_TRACER + T(T_UE_PHY_PUSCH_TX_POWER, T_INT(eNB_id),T_INT(Mod_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx),T_INT(ue->tx_power_dBm[nr_tti_tx]), + T_INT(tx_amp),T_INT(ue->ulsch[eNB_id]->f_pusch),T_INT(get_PL(Mod_id,0,eNB_id)),T_INT(nb_rb)); +#endif + +#ifdef UE_DEBUG_TRACE + LOG_I(PHY,"[UE %d][PUSCH %d] AbsSubFrame %d.%d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", + Mod_id,harq_pid,frame_tx%1024,nr_tti_tx,ue->tx_power_dBm[nr_tti_tx],ue->tx_power_max_dBm, tx_amp); +#endif + + if (tx_amp>100) + tx_amp =100; + + //LOG_I(PHY,"[UE %d][PUSCH %d] after AbsSubFrame %d.%d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", + // Mod_id,harq_pid,frame_tx%1024,nr_tti_tx,ue->tx_power_dBm[nr_tti_tx],ue->tx_power_max_dBm, tx_amp); + + +#if UE_TIMING_TRACE + + start_meas(&ue->ulsch_modulation_stats); +#endif + ulsch_modulation(ue->common_vars.txdataF, + tx_amp, + frame_tx, + nr_tti_tx, + &ue->frame_parms, + ue->ulsch[eNB_id]); + for (aa=0; aa<1/*frame_parms->nb_antennas_tx*/; aa++) + generate_drs_pusch(ue, + proc, + eNB_id, + tx_amp, + nr_tti_tx, + first_rb, + nb_rb, + aa); +#if UE_TIMING_TRACE + stop_meas(&ue->ulsch_modulation_stats); +#endif + } + + if (abstraction_flag==1) { + // clear SR + ue->sr[nr_tti_tx]=0; + } + } // subframe_scheduling_flag==1 + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_OUT); + +} + +void ue_srs_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) +{ + + //NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + //int8_t frame_tx = proc->frame_tx; + int8_t nr_tti_tx = proc->nr_tti_tx; + int16_t tx_amp; + int16_t Po_SRS; + uint8_t nb_rb_srs; + + SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; + uint8_t isSrsTxOccasion = pSoundingrs_ul_config_dedicated->srsUeSubframe; + + if(isSrsTxOccasion) + { + ue->generate_ul_signal[eNB_id] = 1; + if (ue->mac_enabled==1) + { + srs_power_cntl(ue,proc,eNB_id, (uint8_t*)(&nb_rb_srs), abstraction_flag); + Po_SRS = ue->ulsch[eNB_id]->Po_SRS; + } + else + { + Po_SRS = ue->tx_power_max_dBm; + } + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + if (ue->mac_enabled==1) + { + tx_amp = get_tx_amp(Po_SRS, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + nb_rb_srs); + } + else + { + tx_amp = AMP; + } +#else + tx_amp = AMP; +#endif + LOG_D(PHY,"SRS PROC; TX_MAX_POWER %d, Po_SRS %d, NB_RB_UL %d, NB_RB_SRS %d TX_AMPL %d\n",ue->tx_power_max_dBm, + Po_SRS, + ue->frame_parms.N_RB_UL, + nb_rb_srs, + tx_amp); + + uint16_t nsymb = (ue->frame_parms.Ncp==0) ? 14:12; + uint16_t symbol_offset = (int)ue->frame_parms.ofdm_symbol_size*((nr_tti_tx*nsymb)+(nsymb-1)); + generate_srs(&ue->frame_parms, + &ue->soundingrs_ul_config_dedicated[eNB_id], + &ue->common_vars.txdataF[eNB_id][symbol_offset], + tx_amp, + nr_tti_tx); + } +} + +int16_t get_pucch2_cqi(PHY_VARS_NR_UE *ue,int eNB_id,int *len) { + + if ((ue->transmission_mode[eNB_id]<4)|| + (ue->transmission_mode[eNB_id]==7)) { // Mode 1-0 feedback + // 4-bit CQI message + /*LOG_I(PHY,"compute CQI value, TM %d, length 4, Cqi Avg %d, value %d \n", ue->transmission_mode[eNB_id], + ue->measurements.wideband_cqi_avg[eNB_id], + sinr2cqi((double)ue->measurements.wideband_cqi_avg[eNB_id], + ue->transmission_mode[eNB_id]));*/ + *len=4; + return(sinr2cqi((double)ue->measurements.wideband_cqi_avg[eNB_id], + ue->transmission_mode[eNB_id])); + } + else { // Mode 1-1 feedback, later + //LOG_I(PHY,"compute CQI value, TM %d, length 0, Cqi Avg 0 \n", ue->transmission_mode[eNB_id]); + *len=0; + // 2-antenna ports RI=1, 6 bits (2 PMI, 4 CQI) + + // 2-antenna ports RI=2, 8 bits (1 PMI, 7 CQI/DIFF CQI) + return(0); + } +} + + +int16_t get_pucch2_ri(PHY_VARS_NR_UE *ue,int eNB_id) { + + return(1); +} + + +void get_pucch_param(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + uint8_t *ack_payload, + PUCCH_FMT_t format, + uint8_t eNB_id, + uint8_t SR, + uint8_t cqi_report, + uint16_t *pucch_resource, + uint8_t *pucch_payload, + uint16_t *plength) +{ + + switch (format) { + case pucch_format1: + { + pucch_resource[0] = ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex; + pucch_payload[0] = 0; // payload is ignored in case of format1 + pucch_payload[1] = 0; // payload is ignored in case of format1 + } + break; + + case pucch_format1a: + case pucch_format1b: + { + pucch_resource[0] = nr_get_n1_pucch(ue, + proc, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, + eNB_id, + ack_payload, + SR); + pucch_payload[0] = ack_payload[0]; + pucch_payload[1] = ack_payload[1]; + //pucch_payload[1] = 1; + } + break; + + case pucch_format2: + { + pucch_resource[0] = ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex; + if(cqi_report) + { + pucch_payload[0] = get_pucch2_cqi(ue,eNB_id,(int*)plength); + } + else + { + *plength = 1; + pucch_payload[0] = get_pucch2_ri(ue,eNB_id); + } + } + break; + + case pucch_format2a: + case pucch_format2b: + LOG_E(PHY,"NO Resource available for PUCCH 2a/2b \n"); + break; + + case pucch_format3: + fprintf(stderr, "PUCCH format 3 not handled\n"); + abort(); + } +} + +#ifdef NR_PUCCH_SCHED +void ue_nr_pucch_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) { +} +#endif + +void ue_pucch_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) { + + + uint8_t pucch_ack_payload[2]; + uint16_t pucch_resource; + ANFBmode_t bundling_flag; + PUCCH_FMT_t format; + + uint8_t SR_payload; + uint8_t pucch_payload[2]; + uint16_t len; + + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int frame_tx=proc->frame_tx; + int nr_tti_tx=proc->nr_tti_tx; + int Mod_id = ue->Mod_id; + int CC_id = ue->CC_id; + int tx_amp; + int16_t Po_PUCCH; + uint8_t ack_status_cw0=0; + uint8_t ack_status_cw1=0; + uint8_t nb_cw=0; + uint8_t cqi_status=0; + uint8_t ri_status=0; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_IN); + + SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; + + // 36.213 8.2 + /*if ackNackSRS_SimultaneousTransmission == TRUE and in the cell specific SRS subframes UE shall transmit + ACK/NACK and SR using the shortened PUCCH format. This shortened PUCCH format shall be used in a cell + specific SRS nr_tti_rx even if the UE does not transmit SRS in that nr_tti_rx + */ + + int harq_pid = nr_subframe2harq_pid(&ue->frame_parms, + frame_tx, + nr_tti_tx); + + if(ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag) + { + LOG_D(PHY,"PUSCH is programmed on this nr_tti_rx [pid %d] AbsSuframe %d.%d ==> Skip PUCCH transmission \n",harq_pid,frame_tx,nr_tti_tx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_OUT); + return; + } + + uint8_t isShortenPucch = (pSoundingrs_ul_config_dedicated->srsCellSubframe && frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission); + + bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; + + if ((frame_parms->frame_type==FDD) || + (bundling_flag==bundling) || + ((frame_parms->frame_type==TDD)&&(frame_parms->tdd_config==1)&&((nr_tti_tx!=2)||(nr_tti_tx!=7)))) { + format = pucch_format1a; + LOG_D(PHY,"[UE] PUCCH 1a\n"); + } else { + format = pucch_format1b; + LOG_D(PHY,"[UE] PUCCH 1b\n"); + } + + // Part - I + // Collect feedback that should be transmitted at this nr_tti_rx + // - SR + // - ACK/NACK + // - CQI + // - RI + + SR_payload = 0; + if (nr_is_SR_TXOp(ue,proc,eNB_id)==1) + { + if (ue->mac_enabled==1) { + SR_payload = mac_xface->ue_get_SR(Mod_id, + CC_id, + frame_tx, + eNB_id, + ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->crnti, + nr_tti_tx); // nr_tti_rx used for meas gap + } + else { + SR_payload = 1; + } + } + + ack_status_cw0 = nr_get_ack(&ue->frame_parms, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, + nr_tti_tx, + proc->nr_tti_rx, + pucch_ack_payload, + 0); + + ack_status_cw1 = nr_get_ack(&ue->frame_parms, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][1]->harq_ack, + nr_tti_tx, + proc->nr_tti_rx, + pucch_ack_payload, + 1); + + nb_cw = ( (ack_status_cw0 != 0) ? 1:0) + ( (ack_status_cw1 != 0) ? 1:0); + + cqi_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0)&& + (is_cqi_TXOp(ue,proc,eNB_id)==1)); + + ri_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) && + (is_ri_TXOp(ue,proc,eNB_id)==1)); + + // Part - II + // if nothing to report ==> exit function + if( (nb_cw==0) && (SR_payload==0) && (cqi_status==0) && (ri_status==0) ) + { + LOG_D(PHY,"PUCCH No feedback AbsSubframe %d.%d SR_payload %d nb_cw %d pucch_ack_payload[0] %d pucch_ack_payload[1] %d cqi_status %d Return \n", + frame_tx%1024, nr_tti_tx, SR_payload, nb_cw, pucch_ack_payload[0], pucch_ack_payload[1], cqi_status); + return; + } + + // Part - III + // Decide which PUCCH format should be used if needed + format = get_pucch_format(frame_parms->frame_type, + frame_parms->Ncp, + SR_payload, + nb_cw, + cqi_status, + ri_status, + bundling_flag); + // Determine PUCCH resources and payload: mandatory for pucch encoding + get_pucch_param(ue, + proc, + pucch_ack_payload, + format, + eNB_id, + SR_payload, + cqi_status, + &pucch_resource, + (uint8_t *)&pucch_payload, + &len); + + + LOG_D(PHY,"PUCCH feedback AbsSubframe %d.%d SR %d NbCW %d (%d %d) AckNack %d.%d CQI %d RI %d format %d pucch_resource %d pucch_payload %d %d \n", + frame_tx%1024, nr_tti_tx, SR_payload, nb_cw, ack_status_cw0, ack_status_cw1, pucch_ack_payload[0], pucch_ack_payload[1], cqi_status, ri_status, format, pucch_resource,pucch_payload[0],pucch_payload[1]); + + // Part - IV + // Generate PUCCH signal + ue->generate_ul_signal[eNB_id] = 1; + + switch (format) { + case pucch_format1: + case pucch_format1a: + case pucch_format1b: + { + if (ue->mac_enabled == 1) { + Po_PUCCH = nr_pucch_power_cntl(ue,proc,nr_tti_tx,eNB_id,format); + } + else { + Po_PUCCH = ue->tx_power_max_dBm; + } + ue->tx_power_dBm[nr_tti_tx] = Po_PUCCH; + ue->tx_total_RE[nr_tti_tx] = 12; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + tx_amp = get_tx_amp(Po_PUCCH, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + 1); +#else + tx_amp = AMP; +#endif +#if T_TRACER + T(T_UE_PHY_PUCCH_TX_POWER, T_INT(eNB_id),T_INT(Mod_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx),T_INT(ue->tx_power_dBm[nr_tti_tx]), + T_INT(tx_amp),T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->g_pucch),T_INT(get_PL(ue->Mod_id,ue->CC_id,eNB_id))); +#endif + +#ifdef UE_DEBUG_TRACE + if(format == pucch_format1) + { + LOG_I(PHY,"[UE %d][SR %x] AbsSubframe %d.%d Generating PUCCH 1 (SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH %d\n", + Mod_id, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, + frame_tx%1024, nr_tti_tx, + frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, + isShortenPucch, + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, + Po_PUCCH); + } + else + { + if (SR_payload>0) { + LOG_I(PHY,"[UE %d][SR %x] AbsSubFrame %d.%d Generating PUCCH %s payload %d,%d (with SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH %d, amp %d\n", + Mod_id, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, + frame_tx % 1024, nr_tti_tx, + (format == pucch_format1a? "1a": ( + format == pucch_format1b? "1b" : "??")), + pucch_ack_payload[0],pucch_ack_payload[1], + frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, + isShortenPucch, + pucch_resource, + Po_PUCCH, + tx_amp); + } else { + LOG_I(PHY,"[UE %d][PDSCH %x] AbsSubFrame %d.%d rx_offset_diff: %d, Generating PUCCH %s, an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n", + Mod_id, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, + frame_tx%1024, nr_tti_tx,ue->rx_offset_diff, + (format == pucch_format1a? "1a": ( + format == pucch_format1b? "1b" : "??")), + frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, + isShortenPucch, + pucch_resource,pucch_payload[0],pucch_payload[1],SR_payload, + Po_PUCCH, + tx_amp); + } + } +#endif + +#if T_TRACER + if(pucch_payload[0]) + { + T(T_UE_PHY_DLSCH_UE_ACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx), T_INT(Mod_id), T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti), + T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->current_harq_pid)); + } + else + { + T(T_UE_PHY_DLSCH_UE_NACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx), T_INT(Mod_id), T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti), + T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->current_harq_pid)); + } +#endif + + if (abstraction_flag == 0) { + + generate_pucch1x(ue->common_vars.txdataF, + &ue->frame_parms, + ue->ncs_cell, + format, + &ue->pucch_config_dedicated[eNB_id], + pucch_resource, + isShortenPucch, // shortened format + pucch_payload, + tx_amp, + nr_tti_tx); + + } else { +#ifdef PHY_ABSTRACTION + LOG_D(PHY,"Calling generate_pucch_emul ... (ACK %d %d, SR %d)\n",pucch_ack_payload[0],pucch_ack_payload[1],SR_payload); + generate_pucch_emul(ue, + proc, + format, + ue->frame_parms.pucch_config_common.nCS_AN, + pucch_payload, + SR_payload); +#endif + } + } + break; + + + case pucch_format2: + { + if (ue->mac_enabled == 1) { + Po_PUCCH = nr_pucch_power_cntl(ue,proc,nr_tti_tx,eNB_id,format); + } + else { + Po_PUCCH = ue->tx_power_max_dBm; + } + ue->tx_power_dBm[nr_tti_tx] = Po_PUCCH; + ue->tx_total_RE[nr_tti_tx] = 12; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) + tx_amp = get_tx_amp(Po_PUCCH, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + 1); +#else + tx_amp = AMP; +#endif +#if T_TRACER + T(T_UE_PHY_PUCCH_TX_POWER, T_INT(eNB_id),T_INT(Mod_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx),T_INT(ue->tx_power_dBm[nr_tti_tx]), + T_INT(tx_amp),T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->g_pucch),T_INT(get_PL(ue->Mod_id,ue->CC_id,eNB_id))); +#endif +#ifdef UE_DEBUG_TRACE + LOG_I(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (RI or CQI), Po_PUCCH %d, isShortenPucch %d, amp %d\n", + Mod_id, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, + frame_tx%1024, nr_tti_tx, + Po_PUCCH, + isShortenPucch, + tx_amp); +#endif + generate_pucch2x(ue->common_vars.txdataF, + &ue->frame_parms, + ue->ncs_cell, + format, + &ue->pucch_config_dedicated[eNB_id], + pucch_resource, + pucch_payload, + len, // A + 0, // B2 not needed + tx_amp, + nr_tti_tx, + ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->crnti); + } + break; + + case pucch_format2a: + LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2a (RI or CQI) Ack/Nack 1bit \n", + Mod_id, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, + frame_tx%1024, nr_tti_tx); + break; + case pucch_format2b: + LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2b (RI or CQI) Ack/Nack 2bits\n", + Mod_id, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, + frame_tx%1024, nr_tti_tx); + break; + default: + break; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_OUT); + +} + +void phy_procedures_UE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type) { + + + NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + //int32_t ulsch_start=0; + int nr_tti_tx = proc->nr_tti_tx; + int frame_tx = proc->frame_tx; + unsigned int aa; + uint8_t isSubframeSRS; + + uint8_t next1_thread_id = ue->current_thread_id[proc->nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[proc->nr_tti_rx]+1); + uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN); + + LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, nr_tti_tx); +#if T_TRACER + T(T_UE_PHY_UL_TICK, T_INT(ue->Mod_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx)); +#endif + + ue->generate_ul_signal[eNB_id] = 0; +#if UE_TIMING_TRACE + start_meas(&ue->phy_proc_tx); +#endif + +#ifdef EMOS + //phy_procedures_emos_UE_TX(next_slot); +#endif + + ue->tx_power_dBm[nr_tti_tx]=-127; + + if (abstraction_flag==0) { + for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { + memset(&ue->common_vars.txdataF[aa][nr_tti_tx*frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti], + 0, + frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*sizeof(int32_t)); + } + } + + if (ue->UE_mode[eNB_id] != PRACH) { + // check cell srs nr_tti_rx and ue srs nr_tti_rx. This has an impact on pusch encoding + isSubframeSRS = nr_is_srs_occasion_common(&ue->frame_parms,proc->frame_tx,proc->nr_tti_tx); + + ue_compute_srs_occasion(ue,proc,eNB_id,isSubframeSRS); + + ue_ulsch_uespec_procedures(ue,proc,eNB_id,abstraction_flag); + + } + + if (ue->UE_mode[eNB_id] == PUSCH) { + // check if we need to use PUCCH 1a/1b + ue_pucch_procedures(ue,proc,eNB_id,abstraction_flag); + // check if we need to use SRS + ue_srs_procedures(ue,proc,eNB_id,abstraction_flag); + } // UE_mode==PUSCH + + +#ifdef CBA + + if ((ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag >= 1) && + (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == CBA_ACTIVE)) { + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag=0; //-=1 + // ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; + first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; + nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; + //cba_mcs=ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs; + input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; + access_mode=CBA_ACCESS; + + LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: CBA num dci %d\n", + Mod_id,frame_tx,nr_tti_tx, + ue->ulsch[eNB_id]->num_cba_dci[nr_tti_tx]); + + /*mac_xface->ue_get_sdu(Mod_id, + CC_id, + frame_tx, + proc->subframe_tx, + nr_tti_tx%(ue->frame_parms.ttis_per_subframe), + eNB_id, + ulsch_input_buffer, + input_buffer_length, + &access_mode);*/ + + ue->ulsch[eNB_id]->num_cba_dci[nr_tti_tx]=0; + + if (access_mode > UNKNOWN_ACCESS) { + + if (abstraction_flag==0) { + if (ulsch_encoding(ulsch_input_buffer, + ue, + harq_pid, + eNB_id, + proc->nr_tti_rx, + ue->transmission_mode[eNB_id],0, + 0)!=0) { // Nbundled, to be updated!!!! + LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); + return; + } + } + +#ifdef PHY_ABSTRACTION + else { + ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,proc->nr_tti_rx,harq_pid,0); + } + +#endif + } else { + ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; + //reset_cba_uci(ue->ulsch[eNB_id]->o); + LOG_N(PHY,"[UE %d] Frame %d, nr_tti_rx %d: CBA transmission cancelled or postponed\n", + Mod_id, frame_tx,nr_tti_tx); + } + } + +#endif // end CBA + + + if (abstraction_flag == 0) { + ulsch_common_procedures(ue,proc, (ue->generate_ul_signal[eNB_id] == 0)); + } // mode != PRACH + + + if ((ue->UE_mode[eNB_id] == PRACH) && + (ue->frame_parms.prach_config_common.prach_Config_enabled==1)) { + + // check if we have PRACH opportunity + + if (is_prach_subframe(&ue->frame_parms,frame_tx,nr_tti_tx)) { + + ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode); + } + } // mode is PRACH + else { + ue->generate_prach=0; + } + + // reset DL ACK/NACK status + uint8_t N_bundled = 0; + if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0] != NULL) + { + nr_reset_ack(&ue->frame_parms, + ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, + nr_tti_tx, + proc->nr_tti_rx, + ue->ulsch[eNB_id]->o_ACK, + &N_bundled, + 0); + nr_reset_ack(&ue->frame_parms, + ue->dlsch[next1_thread_id][eNB_id][0]->harq_ack, + nr_tti_tx, + proc->nr_tti_rx, + ue->ulsch[eNB_id]->o_ACK, + &N_bundled, + 0); + nr_reset_ack(&ue->frame_parms, + ue->dlsch[next2_thread_id][eNB_id][0]->harq_ack, + nr_tti_tx, + proc->nr_tti_rx, + ue->ulsch[eNB_id]->o_ACK, + &N_bundled, + 0); + } + + if (ue->dlsch_SI[eNB_id] != NULL) + nr_reset_ack(&ue->frame_parms, + ue->dlsch_SI[eNB_id]->harq_ack, + nr_tti_tx, + proc->nr_tti_rx, + ue->ulsch[eNB_id]->o_ACK, + &N_bundled, + 0); + + + LOG_D(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, nr_tti_tx); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&ue->phy_proc_tx); +#endif +} + +void phy_procedures_UE_S_TX(PHY_VARS_NR_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,relaying_type_t r_type) +{ + int aa;//i,aa; + NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + + if (abstraction_flag==0) { + + for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { +#if defined(EXMIMO) //this is the EXPRESS MIMO case + int i; + // set the whole tx buffer to RX + for (i=0; i<LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe; i++) + ue->common_vars.txdata[aa][i] = 0x00010001; + +#else //this is the normal case + memset(&ue->common_vars.txdata[aa][0],0, + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe)*sizeof(int32_t)); +#endif //else EXMIMO + + } + } +} + +void ue_measurement_procedures( + uint16_t l, // symbol index of each slot [0..6] + PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc, uint8_t eNB_id, + uint16_t slot, // slot index of each radio frame [0..19] + uint8_t abstraction_flag,runmode_t mode) +{ + + //LOG_I(PHY,"ue_measurement_procedures l %d Ncp %d\n",l,ue->frame_parms.Ncp); + + NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + + int nr_tti_rx = proc->nr_tti_rx; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN); + + if (l==0) { + // UE measurements on symbol 0 + if (abstraction_flag==0) { + LOG_D(PHY,"Calling measurements nr_tti_rx %d, rxdata %p\n",nr_tti_rx,ue->common_vars.rxdata); + + lte_ue_measurements(ue, + (nr_tti_rx*frame_parms->samples_per_tti+ue->rx_offset)%(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME), + (nr_tti_rx == 1) ? 1 : 0, + 0, + 0, + nr_tti_rx); + } else { + lte_ue_measurements(ue, + 0, + 0, + 1, + 0, + nr_tti_rx); + } +#if T_TRACER + if(slot == 0) + T(T_UE_PHY_MEAS, T_INT(eNB_id), T_INT(ue->Mod_id), T_INT(proc->frame_rx%1024), T_INT(proc->nr_tti_rx), + T_INT((int)(10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB)), + T_INT((int)ue->measurements.rx_rssi_dBm[0]), + T_INT((int)(ue->measurements.rx_power_avg_dB[0] - ue->measurements.n0_power_avg_dB)), + T_INT((int)ue->measurements.rx_power_avg_dB[0]), + T_INT((int)ue->measurements.n0_power_avg_dB), + T_INT((int)ue->measurements.wideband_cqi_avg[0]), + T_INT((int)ue->common_vars.freq_offset)); +#endif + } + + if (l==(6-ue->frame_parms.Ncp)) { + + // make sure we have signal from PSS/SSS for N0 measurement + // LOG_I(PHY," l==(6-ue->frame_parms.Ncp) ue_rrc_measurements\n"); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_IN); + ue_rrc_measurements(ue, + slot, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_OUT); + + if (abstraction_flag==1) + ue->sinr_eff = sinr_eff_cqi_calc(ue, 0, nr_tti_rx); + + } + + // accumulate and filter timing offset estimation every nr_tti_rx (instead of every frame) + if (( (slot%2) == 0) && (l==(4-frame_parms->Ncp))) { + + // AGC + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_IN); + +#ifndef OAI_USRP +#ifndef OAI_BLADERF +#ifndef OAI_LMSSDR +#ifndef OAI_ADRV9371_ZC706 + phy_adjust_gain (ue,dB_fixed(ue->measurements.rssi),0); +#endif +#endif +#endif +#endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT); + + eNB_id = 0; + + if (abstraction_flag == 0) { + if (ue->no_timing_correction==0) + lte_adjust_synch(&ue->frame_parms, + ue, + eNB_id, + nr_tti_rx, + 0, + 16384); + } + + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT); +} + +#ifdef EMOS +void phy_procedures_emos_UE_RX(PHY_VARS_NR_UE *ue,uint8_t last_slot,uint8_t eNB_id) +{ + + uint8_t i,j; + //uint16_t last_slot_emos; + uint32_t bytes; + int Mod_id = ue->Mod_id; + + /* + if (last_slot<2) + last_slot_emos = last_slot; + else if (last_slot>9) + last_slot_emos = last_slot - 8; + else { + LOG_E(PHY,"emos rx last_slot_emos %d, last_slot %d\n", last_slot_emos,last_slot); + //mac_xface->macphy_exit("should never happen"); + } + */ + +#ifdef EMOS_CHANNEL + + if ((last_slot==10) || (last_slot==11)) { + for (i=0; i<ue->frame_parms.nb_antennas_rx; i++) + for (j=0; j<ue->frame_parms.nb_antennas_tx; j++) { + // first OFDM symbol with pilots + memcpy(&emos_dump_UE.channel[i][j][(last_slot%2)*2*ue->frame_parms.ofdm_symbol_size], + &ue->common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][0], + ue->frame_parms.ofdm_symbol_size*sizeof(int)); + // second OFDM symbol with pilots + memcpy(&emos_dump_UE.channel[i][j][((last_slot%2)*2+1)*ue->frame_parms.ofdm_symbol_size], + &ue->common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][(ue->frame_parms.Ncp == 0 ? 4 : 3)*ue->frame_parms.ofdm_symbol_size], + ue->frame_parms.ofdm_symbol_size*sizeof(int)); + } + } + +#endif + + if (last_slot==0) { + emos_dump_UE.timestamp = rt_get_time_ns(); + emos_dump_UE.frame_rx = proc->frame_rx; + emos_dump_UE.UE_mode = ue->UE_mode[eNB_id]; + emos_dump_UE.mimo_mode = ue->transmission_mode[eNB_id]; + emos_dump_UE.freq_offset = ue->common_vars.freq_offset; + emos_dump_UE.timing_advance = ue->timing_advance; + emos_dump_UE.timing_offset = ue->rx_offset; + emos_dump_UE.rx_total_gain_dB = ue->rx_total_gain_dB; + emos_dump_UE.eNb_id = eNB_id; + memcpy(&emos_dump_UE.PHY_measurements,&measurements,sizeof(PHY_MEASUREMENTS)); + } + + if (last_slot==1) { + emos_dump_UE.pbch_errors = ue->pbch_vars[eNB_id]->pdu_errors; + emos_dump_UE.pbch_errors_last = ue->pbch_vars[eNB_id]->pdu_errors_last; + emos_dump_UE.pbch_errors_conseq = ue->pbch_vars[eNB_id]->pdu_errors_conseq; + emos_dump_UE.pbch_fer = ue->pbch_vars[eNB_id]->pdu_fer; + } + + if (last_slot==19) { + emos_dump_UE.dlsch_errors = ue->dlsch_errors[eNB_id]; + emos_dump_UE.dlsch_errors_last = ue->dlsch_errors_last[eNB_id]; + emos_dump_UE.dlsch_received = ue->dlsch_received[eNB_id]; + emos_dump_UE.dlsch_received_last = ue->dlsch_received_last[eNB_id]; + emos_dump_UE.dlsch_fer = ue->dlsch_fer[eNB_id]; + emos_dump_UE.dlsch_cntl_errors = ue->dlsch_SI_errors[eNB_id]; + emos_dump_UE.dlsch_ra_errors = ue->dlsch_ra_errors[eNB_id]; + emos_dump_UE.total_TBS = ue->total_TBS[eNB_id]; + emos_dump_UE.total_TBS_last = ue->total_TBS_last[eNB_id]; + emos_dump_UE.bitrate = ue->bitrate[eNB_id]; + emos_dump_UE.total_received_bits = ue->total_received_bits[eNB_id]; + emos_dump_UE.pmi_saved = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->pmi_alloc; + emos_dump_UE.mcs = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid]->mcs; + emos_dump_UE.use_ia_receiver = openair_daq_vars.use_ia_receiver; + + bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, &emos_dump_UE, sizeof(fifo_dump_emos_UE)); + + if (bytes!=sizeof(fifo_dump_emos_UE)) { + LOG_W(PHY,"[UE %d] frame %d, slot %d, Problem writing EMOS data to FIFO\n",Mod_id,proc->frame_rx, last_slot); + } else { + if (proc->frame_rx%100==0) { + LOG_I(PHY,"[UE %d] frame %d, slot %d, Writing %d bytes EMOS data to FIFO\n",Mod_id,proc->frame_rx, last_slot, bytes); + } + } + } + +} +#endif + + +void restart_phy(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc, uint8_t eNB_id,uint8_t abstraction_flag) +{ + + // uint8_t last_slot; + uint8_t i; + LOG_I(PHY,"[UE %d] frame %d, slot %d, restarting PHY!\n",ue->Mod_id,proc->frame_rx,proc->nr_tti_rx); + //mac_xface->macphy_exit("restart_phy called"); + // first_run = 1; + + if (abstraction_flag ==0 ) { + ue->UE_mode[eNB_id] = NOT_SYNCHED; + } else { + ue->UE_mode[eNB_id] = PRACH; + ue->prach_resources[eNB_id]=NULL; + } + + proc->frame_rx = -1; + proc->frame_tx = -1; + // ue->synch_wait_cnt=0; + // ue->sched_cnt=-1; + + ue->pbch_vars[eNB_id]->pdu_errors_conseq=0; + ue->pbch_vars[eNB_id]->pdu_errors=0; + + ue->pdcch_vars[0][eNB_id]->dci_errors = 0; + ue->pdcch_vars[0][eNB_id]->dci_missed = 0; + ue->pdcch_vars[0][eNB_id]->dci_false = 0; + ue->pdcch_vars[0][eNB_id]->dci_received = 0; + + ue->pdcch_vars[1][eNB_id]->dci_errors = 0; + ue->pdcch_vars[1][eNB_id]->dci_missed = 0; + ue->pdcch_vars[1][eNB_id]->dci_false = 0; + ue->pdcch_vars[1][eNB_id]->dci_received = 0; + + ue->dlsch_errors[eNB_id] = 0; + ue->dlsch_errors_last[eNB_id] = 0; + ue->dlsch_received[eNB_id] = 0; + ue->dlsch_received_last[eNB_id] = 0; + ue->dlsch_fer[eNB_id] = 0; + ue->dlsch_SI_received[eNB_id] = 0; + ue->dlsch_ra_received[eNB_id] = 0; + ue->dlsch_p_received[eNB_id] = 0; + ue->dlsch_SI_errors[eNB_id] = 0; + ue->dlsch_ra_errors[eNB_id] = 0; + ue->dlsch_p_errors[eNB_id] = 0; + + ue->dlsch_mch_received[eNB_id] = 0; + + for (i=0; i < MAX_MBSFN_AREA ; i ++) { + ue->dlsch_mch_received_sf[i][eNB_id] = 0; + ue->dlsch_mcch_received[i][eNB_id] = 0; + ue->dlsch_mtch_received[i][eNB_id] = 0; + ue->dlsch_mcch_errors[i][eNB_id] = 0; + ue->dlsch_mtch_errors[i][eNB_id] = 0; + ue->dlsch_mcch_trials[i][eNB_id] = 0; + ue->dlsch_mtch_trials[i][eNB_id] = 0; + } + + //ue->total_TBS[eNB_id] = 0; + //ue->total_TBS_last[eNB_id] = 0; + //ue->bitrate[eNB_id] = 0; + //ue->total_received_bits[eNB_id] = 0; +} + + +void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc, uint8_t abstraction_flag) +{ + + // int i; + int pbch_tx_ant=0; + uint8_t pbch_phase; + uint16_t frame_tx; + static uint8_t first_run = 1; + uint8_t pbch_trials = 0; + + DevAssert(ue); + + int frame_rx = proc->frame_rx; + int nr_tti_rx = proc->nr_tti_rx; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN); + + pbch_phase=(frame_rx%4); + + if (pbch_phase>=4) + pbch_phase=0; + + 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 (abstraction_flag == 0) { + pbch_tx_ant = rx_pbch(ue, proc, + ue->pbch_vars[eNB_id], + &ue->frame_parms, + eNB_id, + ue->frame_parms.mode1_flag==1?SISO:ALAMOUTI, + ue->high_speed_flag, + pbch_phase); + + + + } + +#ifdef PHY_ABSTRACTION + else { + pbch_tx_ant = rx_pbch_emul(ue, + eNB_id, + pbch_phase); + } + +#endif + + if ((pbch_tx_ant>0) && (pbch_tx_ant<=4)) { + break; + } + + pbch_phase++; + + if (pbch_phase>=4) + pbch_phase=0; + } + + + + if ((pbch_tx_ant>0) && (pbch_tx_ant<=4)) { + + if (opt_enabled) { + static uint8_t dummy[3]; + dummy[0] = ue->pbch_vars[eNB_id]->decoded_output[2]; + dummy[1] = ue->pbch_vars[eNB_id]->decoded_output[1]; + dummy[2] = ue->pbch_vars[eNB_id]->decoded_output[0]; + trace_pdu(1, dummy, 3, ue->Mod_id, 0, 0, + frame_rx, nr_tti_rx, 0, 0); + LOG_D(OPT,"[UE %d][PBCH] Frame %d trace pdu for PBCH\n", + ue->Mod_id, nr_tti_rx); + } + + if (pbch_tx_ant>2) { + LOG_W(PHY,"[openair][SCHED][SYNCH] PBCH decoding: pbch_tx_ant>2 not supported\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); + return; + } + + + ue->pbch_vars[eNB_id]->pdu_errors_conseq = 0; + frame_tx = (((int)(ue->pbch_vars[eNB_id]->decoded_output[2]&0x03))<<8); + frame_tx += ((int)(ue->pbch_vars[eNB_id]->decoded_output[1]&0xfc)); + frame_tx += pbch_phase; + + //if (ue->mac_enabled==1) { + //mac_xface->dl_phy_sync_success(ue->Mod_id,frame_rx,eNB_id,first_run); + //} + +#ifdef EMOS + //emos_dump_UE.frame_tx = frame_tx; + //emos_dump_UE.mimo_mode = ue->pbch_vars[eNB_id]->decoded_output[1]; +#endif + + if (first_run) { + first_run = 0; + + proc->frame_rx = (proc->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); + proc->frame_tx = proc->frame_rx; + for(int th_id=0; th_id<RX_NB_TH; th_id++) + { + ue->proc.proc_rxtx[th_id].frame_rx = proc->frame_rx; + ue->proc.proc_rxtx[th_id].frame_tx = proc->frame_tx; + + printf("[UE %d] frame %d, nr_tti_rx %d: Adjusting frame counter (PBCH ant_tx=%d, frame_tx=%d, phase %d, rx_offset %d) => new frame %d\n", + ue->Mod_id, + ue->proc.proc_rxtx[th_id].frame_rx, + nr_tti_rx, + pbch_tx_ant, + frame_tx, + pbch_phase, + ue->rx_offset, + proc->frame_rx); + } + + + frame_rx = proc->frame_rx; + + } else if (((frame_tx & 0x03FF) != (proc->frame_rx & 0x03FF))) { + //(pbch_tx_ant != ue->frame_parms.nb_antennas_tx)) { + LOG_D(PHY,"[UE %d] frame %d, nr_tti_rx %d: Re-adjusting frame counter (PBCH ant_tx=%d, frame_rx=%d, frame%%1024=%d, phase %d).\n", + ue->Mod_id, + proc->frame_rx, + nr_tti_rx, + pbch_tx_ant, + frame_tx, + frame_rx & 0x03FF, + pbch_phase); + + proc->frame_rx = (proc->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); + proc->frame_tx = proc->frame_rx; + frame_rx = proc->frame_rx; + + for(int th_id=0; th_id<RX_NB_TH; th_id++) + { + ue->proc.proc_rxtx[th_id].frame_rx = (proc->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); + ue->proc.proc_rxtx[th_id].frame_tx = proc->frame_rx; + } + + } + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] frame %d, nr_tti_rx %d, Received PBCH (MIB): mode1_flag %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n", + ue->Mod_id, + frame_rx, + nr_tti_rx, + ue->frame_parms.mode1_flag, + 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); +#endif + + } else { + /* + LOG_E(PHY,"[UE %d] frame %d, nr_tti_rx %d, Error decoding PBCH!\n", + ue->Mod_id,frame_rx, nr_tti_rx); + + LOG_I(PHY,"[UE %d] rx_offset %d\n",ue->Mod_id,ue->rx_offset); + + + write_output("rxsig0.m","rxs0", ue->common_vars.rxdata[0],ue->frame_parms.samples_per_subframe,1,1); + + write_output("H00.m","h00",&(ue->common_vars.dl_ch_estimates[0][0][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1); + write_output("H10.m","h10",&(ue->common_vars.dl_ch_estimates[0][2][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1); + + write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],8*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("PBCH_rxF0_ext.m","pbch0_ext",ue->pbch_vars[0]->rxdataF_ext[0],12*4*6,1,1); + write_output("PBCH_rxF0_comp.m","pbch0_comp",ue->pbch_vars[0]->rxdataF_comp[0],12*4*6,1,1); + write_output("PBCH_rxF_llr.m","pbch_llr",ue->pbch_vars[0]->llr,(ue->frame_parms.Ncp==0) ? 1920 : 1728,1,4); + exit(-1); + */ + + ue->pbch_vars[eNB_id]->pdu_errors_conseq++; + ue->pbch_vars[eNB_id]->pdu_errors++; + if (ue->mac_enabled == 1) { + //mac_xface->out_of_sync_ind(ue->Mod_id,frame_rx,eNB_id); + } + else{ + if (ue->pbch_vars[eNB_id]->pdu_errors_conseq>=100) { + LOG_E(PHY,"More that 100 consecutive PBCH errors! Exiting!\n"); + //mac_xface->macphy_exit("More that 100 consecutive PBCH errors!"); + } + } + } + + if (frame_rx % 100 == 0) { + ue->pbch_vars[eNB_id]->pdu_fer = ue->pbch_vars[eNB_id]->pdu_errors - ue->pbch_vars[eNB_id]->pdu_errors_last; + ue->pbch_vars[eNB_id]->pdu_errors_last = ue->pbch_vars[eNB_id]->pdu_errors; + } + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] frame %d, slot %d, PBCH errors = %d, consecutive errors = %d!\n", + ue->Mod_id,frame_rx, nr_tti_rx, + ue->pbch_vars[eNB_id]->pdu_errors, + ue->pbch_vars[eNB_id]->pdu_errors_conseq); +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); +} + + +#endif //(0) + +#ifdef NR_PDCCH_SCHED +int nr_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t abstraction_flag) +{ + + // unsigned int dci_cnt=0, i; //removed for nr_ue_pdcch_procedures and added in the loop for nb_coreset_active + #ifdef NR_PDCCH_SCHED_DEBUG + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_ue_pdcch_procedures() \n"); + #endif + + int frame_rx = proc->frame_rx; + int nr_tti_rx = proc->nr_tti_rx; + NR_DCI_ALLOC_t dci_alloc_rx[8]; + uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); + uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); + + uint16_t tc_rnti = 1; // FIXME + uint16_t int_rnti = 1; // FIXME + uint16_t sfi_rnti = 1; // FIXME + uint16_t tpc_pusch_rnti =1; // FIXME + uint16_t tpc_pucch_rnti = 1; // FIXME + uint16_t tpc_srs_rnti = 1; // FIXME + // s in TS 38.212 Subclause 10.1, for each active BWP the UE can deal with 10 different search spaces + // FIXME ! this value has to be obtained by higher-layer parameters + int nb_searchspace_total = NR_NBR_SEARCHSPACE_ACT_BWP - 1; + // p in TS 38.212 Subclause 10.1, for each active BWP the UE can deal with 3 different CORESETs (including coresetId 0 for common search space) + // FIXME ! this value will be obtained from IE PDCCH-Config or PDCCH-ConfigCommon (SIB) + int nb_coreset_total = NR_NBR_CORESET_ACT_BWP - 1; + int nb_searchspace_active=0; + NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; + NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; + + // First we have to identify each searchSpace active at a time and do PDCCH monitoring corresponding to current searchSpace + // Up to 10 searchSpaces can be configured to UE (s<=10) + for (nb_searchspace_active=0; nb_searchspace_active<nb_searchspace_total; nb_searchspace_active++){ + int nb_coreset_active=0; + // Verify that monitoring is required at the slot nr_tti_rx. We will run pdcch procedure only if do_pdcch_monitoring_current_slot=1 + int do_pdcch_monitoring_current_slot=0; + // For Type0-PDCCH searchspace, we need to calculate the monitoring slot from Tables 13-1 .. 13-15 in TS 38.213 Subsection 13 + NR_UE_SLOT_PERIOD_OFFSET_t sl_period_offset_mon = pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset; + if (sl_period_offset_mon == sl1) { + do_pdcch_monitoring_current_slot=1; // PDCCH monitoring in every slot + } else if (nr_tti_rx%(int)sl_period_offset_mon == pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset_offset) { + do_pdcch_monitoring_current_slot=1; // PDCCH monitoring in every monitoringSlotPeriodicityAndOffset slot with offset + } + /* + * FIXME + * For PDCCH monitoring when overlap with SS/PBCH according to 38.213 v15.1.0 Section 10 + * To be implemented LATER !!! + */ + #ifdef NR_PDCCH_SCHED_DEBUG + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> nb_searchspace_active=%d do_pdcch_monitoring_current_slot=%d\n", + nb_searchspace_active, + do_pdcch_monitoring_current_slot); + #endif + + if (do_pdcch_monitoring_current_slot) { + // the searchSpace indicates that we need to monitor PDCCH in current nr_tti_rx + // get the parameters describing the current SEARCHSPACE + int searchSpace_id = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceId; + // the CORESET id applicable to the current SearchSpace + int searchSpace_coreset_id = pdcch_vars2->searchSpace[nb_searchspace_active].controlResourceSetId; + // FIXME this variable is a bit string (14 bits) identifying every OFDM symbol in a slot. + // at the moment we will not take into consideration this variable and we will consider that the OFDM symbol offset is always the first OFDM in a symbol + uint16_t symbol_within_slot_mon = pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSymbolWithinSlot; + // get the remaining parameters describing the current SEARCHSPACE: // FIXME! To be defined where we get this information from + NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L1 = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel1; + NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L2 = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel2; + NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L4 = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel4; + NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L8 = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel8; + NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L16 = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel16; + // FIXME! A table of five enum elements + // searchSpaceType indicates whether this is a common search space or a UE-specific search space + int searchSpaceType = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceType.type; + + while ((searchSpace_coreset_id != pdcch_vars2->coreset[nb_coreset_active].controlResourceSetId) && (nb_coreset_active<nb_coreset_total)) { + // we need to identify the CORESET associated to the active searchSpace + nb_coreset_active++; + } + if (nb_coreset_active >= nb_coreset_total) return 0; // the coreset_id could not be found. There is a problem + + unsigned int dci_cnt=0, i; + + // get the parameters describing the current CORESET + int coreset_duration = pdcch_vars2->coreset[nb_coreset_active].duration; + uint64_t coreset_freq_dom = pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources; + int coreset_shift_index = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.shiftIndex; + NR_UE_CORESET_REG_bundlesize_t coreset_bundlesize = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.reg_bundlesize; + NR_UE_CORESET_interleaversize_t coreset_interleaversize = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.interleaversize; + NR_UE_CORESET_precoder_granularity_t precoder_granularity = pdcch_vars2->coreset[nb_coreset_active].precoderGranularity; + int tci_statesPDCCH = pdcch_vars2->coreset[nb_coreset_active].tciStatesPDCCH; + int tci_present = pdcch_vars2->coreset[nb_coreset_active].tciPresentInDCI; + uint16_t pdcch_DMRS_scrambling_id = pdcch_vars2->coreset[nb_coreset_active].pdcchDMRSScramblingID; + + // this table contains 48 (NBR_NR_DCI_FIELDS) elements for each dci field described in TS 38.212. Each element represents the size in bits for each dci field + uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS] = {0}; + // this is the UL bandwidth part. FIXME! To be defined where this value comes from + uint16_t n_RB_ULBWP = 100; + // this is the DL bandwidth part. FIXME! To be defined where this value comes from + uint16_t n_RB_DLBWP = 100; + + // A set of PDCCH candidates for a UE to monitor is defined in terms of PDCCH search spaces. + // Searchspace types: + // Type0-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI + // number of consecutive resource blocks and a number of consecutive symbols for + // the control resource set of the Type0-PDCCH common search space from + // the four most significant bits of RMSI-PDCCH-Config as described in Tables 13-1 through 13-10 + // and determines PDCCH monitoring occasions + // from the four least significant bits of RMSI-PDCCH-Config, + // included in MasterInformationBlock, as described in Tables 13-11 through 13-15 + // Type0A-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI + // Type1-PDCCH common search space for a DCI format with CRC scrambled by a RA-RNTI, or a TC-RNTI, or a C-RNTI + // Type2-PDCCH common search space for a DCI format with CRC scrambled by a P-RNTI + // Type3-PDCCH common search space for a DCI format with CRC scrambled by INT-RNTI, or SFI-RNTI, + // or TPC-PUSCH-RNTI, or TPC-PUCCH-RNTI, or TPC-SRS-RNTI, or C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI + + +#ifdef PHY_ABSTRACTION + int CC_id; + int UE_id; + uint8_t harq_pid; +#endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_IN); +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_rx_pdcch_stats); +#endif + + // if (nr_tti_rx != 5) + // return 0; + if (abstraction_flag == 0) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN); +/* rx_pdcch(ue, + proc->frame_rx, + nr_tti_rx, + eNB_id, + (ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, + ue->high_speed_flag, + ue->is_secondary_ue);*/ //removed for nr_ue_pdcch_procedures + #ifdef NR_PDCCH_SCHED_DEBUG + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_rx_pdcch(nb_coreset_active=%d, searchSpaceType=%d)\n", + nb_coreset_active, + searchSpaceType); + #endif + nr_rx_pdcch(ue, + proc->frame_rx, + nr_tti_rx, + eNB_id, + //(ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, // NR_DL_FRAME_PARMS struct has been modified, and 'mode1_flag' needs to be included + SISO, + ue->high_speed_flag, + ue->is_secondary_ue, + nb_coreset_active, + (symbol_within_slot_mon&0x3FFF), + searchSpaceType); + #ifdef NR_PDCCH_SCHED_DEBUG + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_rx_pdcch(nb_coreset_active=%d, searchSpaceType=%d)\n", + nb_coreset_active, + searchSpaceType); + #endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_IN); + +/* + //printf("Decode SIB frame param agregation + DCI %d %d \n",agregationLevel,dciFormat); + + //agregation level == FF means no configuration on + if(ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->agregationLevel == 0xFF || ue->decode_SIB) + { + // search all possible dcis + dci_cnt = dci_decoding_procedure(ue, + dci_alloc_rx, + (ue->UE_mode[eNB_id] < PUSCH)? 1 : 0, // if we're in PUSCH don't listen to common search space, + // later when we need paging or RA during connection, update this ... + eNB_id,nr_tti_rx); + } + else + { + // search only preconfigured dcis + // search C RNTI dci + dci_cnt = dci_CRNTI_decoding_procedure(ue, + dci_alloc_rx, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dciFormat, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->agregationLevel, + eNB_id, + nr_tti_rx); + } +*/ //removed for nr_ue_pdcch_procedures + if (searchSpaceType == common) { // search all possible dci's for COMMON SEARCH SPACES according to the current SEARCHSPACE configuration + #ifdef NR_PDCCH_SCHED_DEBUG + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_dci_decoding_procedure(searchSpaceType=%d, nb_searchspace_active=%d, nb_coreset_active=%d) -> dci_cnt=%d\n", + searchSpaceType, + nb_searchspace_active, + nb_coreset_active, + dci_cnt); + #endif + dci_cnt = nr_dci_decoding_procedure(nb_searchspace_active, + nb_coreset_active, + ue, + dci_alloc_rx, + searchSpaceType, // if we're in PUSCH don't listen to common search space, + // later when we need paging or RA during connection, update this ... + eNB_id, + nr_tti_rx, + dci_fields_sizes, + n_RB_ULBWP, + n_RB_DLBWP); + #ifdef NR_PDCCH_SCHED_DEBUG + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_dci_decoding_procedure() -> dci_cnt=%d\n",dci_cnt); + #endif + } + if (searchSpaceType == ue_specific){// search all possible dci's for UE-SPECIFIC SEARCH SPACES according to the current SEARCHSPACE configuration + #ifdef NR_PDCCH_SCHED_DEBUG + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_dci_decoding_procedure(searchSpaceType=%d, nb_searchspace_active=%d, nb_coreset_active=%d) -> dci_cnt=%d\n", + searchSpaceType, + nb_searchspace_active, + nb_coreset_active, + dci_cnt); + #endif + dci_cnt = nr_dci_decoding_procedure(nb_searchspace_active, + nb_coreset_active, + ue, + dci_alloc_rx, + searchSpaceType, // if we're in PUSCH don't listen to common search space, + // later when we need paging or RA during connection, update this ... + eNB_id, + nr_tti_rx, + dci_fields_sizes, + n_RB_ULBWP, + n_RB_DLBWP); + #ifdef NR_PDCCH_SCHED_DEBUG + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_dci_decoding_procedure() -> dci_cnt=%d\n",dci_cnt); + #endif + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT); + //LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d PHICH RX\n",ue->Mod_id,frame_rx,nr_tti_rx); + + /* if (is_phich_subframe(&ue->frame_parms,nr_tti_rx)) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH, VCD_FUNCTION_IN); + rx_phich(ue,proc,nr_tti_rx,eNB_id); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH, VCD_FUNCTION_OUT); + }*/ //removed for nr_ue_pdcch_procedures + } +#if 0 + #ifdef PHY_ABSTRACTION + else { + for (i=0; i<NB_eNB_INST; i++) { + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) + if (PHY_vars_eNB_g[i][CC_id]->frame_parms.Nid_cell == ue->frame_parms.Nid_cell) + break; + + if (CC_id < MAX_NUM_CCs) + break; + } + + if (i==NB_eNB_INST) { + LOG_E(PHY,"[UE %d] phy_procedures_lte_ue.c: FATAL : Could not find attached eNB for DCI emulation (Nid_cell %d)!!!!\n",ue->Mod_id,ue->frame_parms.Nid_cell); + //mac_xface->macphy_exit("Could not find attached eNB for DCI emulation"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); + return(-1); + } + + LOG_D(PHY,"Calling dci_decoding_proc_emul ...\n"); + dci_cnt = dci_decoding_procedure_emul(ue->pdcch_vars[nr_tti_rx&1], + PHY_vars_eNB_g[i][CC_id]->num_ue_spec_dci[nr_tti_rx&1], + PHY_vars_eNB_g[i][CC_id]->num_common_dci[nr_tti_rx&1], + PHY_vars_eNB_g[i][CC_id]->dci_alloc[nr_tti_rx&1], + dci_alloc_rx, + eNB_id); + // printf("DCI: dci_cnt %d\n",dci_cnt); + UE_id = (uint32_t)nr_find_ue((int16_t)ue->pdcch_vars[nr_tti_rx&1][eNB_id]->crnti,PHY_vars_eNB_g[i][CC_id]); + + if (UE_id>=0) { + // printf("Checking PHICH for UE %d (eNB %d)\n",UE_id,i); + //if (is_phich_subframe(&ue->frame_parms,nr_tti_rx)) { + //harq_pid = phich_subframe_to_harq_pid(&ue->frame_parms,frame_rx,nr_tti_rx); + //if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == ACTIVE) { + //ue->ulsch[eNB_id]->harq_processes[harq_pid]->phich_ACK=1; + //ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag =0; + //ue->ulsch[eNB_id]->harq_processes[harq_pid]->status = IDLE; + //ue->ulsch_Msg3_active[eNB_id] = 0; + //ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; + //LOG_D(PHY,"Msg3 inactive\n"); + //} // harq_pid is ACTIVE + //} // This is a PHICH nr_tti_rx + } // UE_id exists + } + + #endif +#endif + uint8_t *nCCE_current = &ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->nCCE[nr_tti_rx]; + uint8_t *nCCE_dest = &ue->pdcch_vars[next1_thread_id][eNB_id]->nCCE[nr_tti_rx]; + uint8_t *nCCE_dest1 = &ue->pdcch_vars[next2_thread_id][eNB_id]->nCCE[nr_tti_rx]; + memcpy(nCCE_dest, nCCE_current, sizeof(uint8_t)); + memcpy(nCCE_dest1, nCCE_current, sizeof(uint8_t)); + + LOG_D(PHY,"current_thread %d next1_thread %d next2_thread %d \n", ue->current_thread_id[nr_tti_rx], next1_thread_id, next2_thread_id); + + LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d, Mode %s: DCI found %i --> rnti %x / crnti %x : format %d\n", + ue->Mod_id,frame_rx%1024,nr_tti_rx,mode_string[ue->UE_mode[eNB_id]], + dci_cnt, + dci_alloc_rx[0].rnti, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + dci_alloc_rx[0].format ); + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dci_received += dci_cnt; + +#ifdef EMOS + //emos_dump_UE.dci_cnt[nr_tti_rx] = dci_cnt; +#endif + + for (i=0; i<dci_cnt; i++) { + /* + * This is the NR part + */ + if ((dci_alloc_rx[i].rnti == SI_RNTI) && (dci_alloc_rx[i].format == format1_0)){ + nr_generate_ue_ul_dlsch_params_from_dci(ue, + eNB_id, + frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + dci_alloc_rx[i].dci_length, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->ulsch[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->crnti_is_temporary? ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti: 0, + &dci_fields_sizes, + n_RB_ULBWP, + n_RB_DLBWP); + ue->dlsch_SI_received[eNB_id]++; + } + + if ((dci_alloc_rx[i].rnti == P_RNTI) && (dci_alloc_rx[i].format == format1_0)){ + ue->dlsch_p_received[eNB_id]++; + } + + if ((dci_alloc_rx[i].rnti == ue->prach_resources[eNB_id]->ra_RNTI) && (dci_alloc_rx[i].format == format1_0)){ + nr_generate_ue_ul_dlsch_params_from_dci(ue, + eNB_id, + frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + dci_alloc_rx[i].dci_length, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->ulsch[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + ue->prach_resources[eNB_id]->ra_RNTI, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->crnti_is_temporary? ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti: 0, + &dci_fields_sizes, + n_RB_ULBWP, + n_RB_DLBWP); + ue->dlsch_ra_received[eNB_id]++; + } + + if ((dci_alloc_rx[i].rnti == sfi_rnti) && (dci_alloc_rx[i].format == format2_0)){ + } + + if ((dci_alloc_rx[i].rnti == int_rnti) && (dci_alloc_rx[i].format == format2_1)){ + } + + if ((dci_alloc_rx[i].rnti == tpc_pusch_rnti) && (dci_alloc_rx[i].format == format2_2)){ + } + + if ((dci_alloc_rx[i].rnti == tpc_srs_rnti) && (dci_alloc_rx[i].format == format2_3)){ + } + + if ((dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && (dci_alloc_rx[i].format == format0_0)){ + nr_generate_ue_ul_dlsch_params_from_dci(ue, + eNB_id, + frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + dci_alloc_rx[i].dci_length, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->ulsch[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->crnti_is_temporary? ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti: 0, + &dci_fields_sizes, + n_RB_ULBWP, + n_RB_DLBWP); + } + + if ((dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && (dci_alloc_rx[i].format == format0_1)){ // This format not implemented at a first time. FIXME + } + + if ((dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && (dci_alloc_rx[i].format == format1_0)){ + nr_generate_ue_ul_dlsch_params_from_dci(ue, + eNB_id, + frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + dci_alloc_rx[i].dci_length, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->ulsch[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->crnti_is_temporary? ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti: 0, + &dci_fields_sizes, + n_RB_ULBWP, + n_RB_DLBWP); + ue->dlsch_received[eNB_id]++; + } + + if ((dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && (dci_alloc_rx[i].format == format1_1)){ // This format not implemented at a first time. FIXME + } + +#if 0 + /* + * This is the LTE part to be removed + */ + if ((ue->UE_mode[eNB_id]>PRACH) && (dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && (dci_alloc_rx[i].format != format0)) { + + LOG_D(PHY,"[UE %d][DCI][PDSCH %x] AbsSubframe %d.%d: format %d, num_pdcch_symbols %d, nCCE %d, total CCEs %d\n", + ue->Mod_id,dci_alloc_rx[i].rnti, + frame_rx%1024,nr_tti_rx, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->nCCE[nr_tti_rx], + get_nCCE(3,&ue->frame_parms,get_mi(&ue->frame_parms,0))); + + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + + if ((ue->UE_mode[eNB_id] > PRACH) && + (generate_ue_dlsch_params_from_dci(frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->crnti_is_temporary? ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti: 0)==0)) { + + // update TPC for PUCCH + if((dci_alloc_rx[i].format == format1) || + (dci_alloc_rx[i].format == format1A) || + (dci_alloc_rx[i].format == format1B) || + (dci_alloc_rx[i].format == format2) || + (dci_alloc_rx[i].format == format2A) || + (dci_alloc_rx[i].format == format2B)) + { + //ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->g_pucch += ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid]->delta_PUCCH; + int32_t delta_pucch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid]->delta_PUCCH; + for(int th_id=0; th_id<RX_NB_TH; th_id++) + { + ue->dlsch[th_id][eNB_id][0]->g_pucch += delta_pucch; + } + LOG_D(PHY,"update TPC for PUCCH %d.%d / pid %d delta_PUCCH %d g_pucch %d %d \n",frame_rx, nr_tti_rx,ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid, + delta_pucch, + ue->dlsch[0][eNB_id][0]->g_pucch, + ue->dlsch[1][eNB_id][0]->g_pucch + //ue->dlsch[2][eNB_id][0]->g_pucch + ); + } + + ue->dlsch_received[eNB_id]++; + + #ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Generated UE DLSCH C_RNTI format %d\n",ue->Mod_id,dci_alloc_rx[i].format); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + LOG_D(PHY,"[UE %d] *********** dlsch->active in nr_tti_rx %d=> %d\n",ue->Mod_id,nr_tti_rx,ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active); + #endif + + // we received a CRNTI, so we're in PUSCH + if (ue->UE_mode[eNB_id] != PUSCH) { + #ifdef DEBUG_PHY_PROC + LOG_I(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Received DCI with CRNTI %x => Mode PUSCH\n",ue->Mod_id,frame_rx,nr_tti_rx,ue->pdcch_vars[nr_tti_rx&1][eNB_id]->crnti); + #endif + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + ue->UE_mode[eNB_id] = PUSCH; + //mac_xface->macphy_exit("Connected. Exiting\n"); + } + } else { + LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Problem in DCI!\n",ue->Mod_id,frame_rx,nr_tti_rx); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + } + } + + else if ((dci_alloc_rx[i].rnti == SI_RNTI) && + ((dci_alloc_rx[i].format == format1A) || (dci_alloc_rx[i].format == format1C))) { + + #ifdef DEBUG_PHY_PROC + LOG_I(PHY,"[UE %d] nr_tti_rx %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,nr_tti_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); + #endif + + + if (generate_ue_dlsch_params_from_dci(frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + SI_RNTI, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars_SI[eNB_id], + &ue->dlsch_SI[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + 0)==0) { + + ue->dlsch_SI_received[eNB_id]++; + + + LOG_I(PHY,"[UE %d] Frame %d, nr_tti_rx %d : Generate UE DLSCH SI_RNTI format 1%s\n",ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].format==format1A?"A":"C"); + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + + } + } + + else if ((dci_alloc_rx[i].rnti == P_RNTI) && + ((dci_alloc_rx[i].format == format1A) || (dci_alloc_rx[i].format == format1C))) { + + #ifdef DEBUG_PHY_PROC + LOG_I(PHY,"[UE %d] nr_tti_rx %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,nr_tti_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); + #endif + + + if (generate_ue_dlsch_params_from_dci(frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + P_RNTI, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars_p[eNB_id], + &ue->dlsch_SI[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + 0)==0) { + + ue->dlsch_p_received[eNB_id]++; + LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d : Generate UE DLSCH P_RNTI format 1%s\n",ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].format==format1A?"A":"C"); + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + + } + } + + else if ((ue->prach_resources[eNB_id]) && + (dci_alloc_rx[i].rnti == ue->prach_resources[eNB_id]->ra_RNTI) && + (dci_alloc_rx[i].format == format1A)) { + + #ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][RAPROC] nr_tti_rx %d: Found RA rnti %x, format 1A, dci_cnt %d\n",ue->Mod_id,nr_tti_rx,dci_alloc_rx[i].rnti,i); + + //if (((frame_rx%100) == 0) || (frame_rx < 20)) + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + //mac_xface->macphy_exit("so far so good...\n"); + #endif + + + if (generate_ue_dlsch_params_from_dci(frame_rx, + nr_tti_rx, + (DCI1A_5MHz_TDD_1_6_t *)&dci_alloc_rx[i].dci_pdu, + ue->prach_resources[eNB_id]->ra_RNTI, + format1A, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars_ra[eNB_id], + &ue->dlsch_ra[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + ue->prach_resources[eNB_id]->ra_RNTI, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + 0)==0) { + + ue->dlsch_ra_received[eNB_id]++; + + #ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Generate UE DLSCH RA_RNTI format 1A, rb_alloc %x, dlsch_ra[eNB_id] %p\n", + ue->Mod_id,ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even[0],ue->dlsch_ra[eNB_id]); + #endif + } + } else if( (dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && + (dci_alloc_rx[i].format == format0)) { + + #ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d: Found rnti %x, format 0, dci_cnt %d\n", + ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].rnti,i); + #endif + + ue->ulsch_no_allocation_counter[eNB_id] = 0; + //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); + + if ((ue->UE_mode[eNB_id] > PRACH) && + (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + nr_tti_rx, + format0, + ue, + proc, + SI_RNTI, + 0, + P_RNTI, + CBA_RNTI, + eNB_id, + 0)==0)) { + #if T_TRACER + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + uint8_t harq_pid = nr_subframe2harq_pid(frame_parms, + nr_pdcch_alloc2ul_frame(frame_parms,proc->frame_rx,proc->nr_tti_rx), + nr_pdcch_alloc2ul_subframe(frame_parms,proc->nr_tti_rx)); + + T(T_UE_PHY_ULSCH_UE_DCI, T_INT(eNB_id), T_INT(proc->frame_rx%1024), T_INT(proc->nr_tti_rx), T_INT(ue->Mod_id), + T_INT(dci_alloc_rx[i].rnti), T_INT(harq_pid), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->round), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS)); + #endif + #ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Generate UE ULSCH C_RNTI format 0 (nr_tti_rx %d)\n",ue->Mod_id,nr_tti_rx); + #endif + + } + } else if( (dci_alloc_rx[i].rnti == ue->ulsch[eNB_id]->cba_rnti[0]) && + (dci_alloc_rx[i].format == format0)) { + // UE could belong to more than one CBA group + // ue->Mod_id%ue->ulsch[eNB_id]->num_active_cba_groups] + #ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d: Found cba rnti %x, format 0, dci_cnt %d\n", + ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].rnti,i); + /* + if (((frame_rx%100) == 0) || (frame_rx < 20)) + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + */ + #endif + + ue->ulsch_no_allocation_counter[eNB_id] = 0; + //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); + + if ((ue->UE_mode[eNB_id] > PRACH) && + (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, + ue->ulsch[eNB_id]->cba_rnti[0], + nr_tti_rx, + format0, + ue, + proc, + SI_RNTI, + 0, + P_RNTI, + CBA_RNTI, + eNB_id, + 0)==0)) { + + #ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Generate UE ULSCH CBA_RNTI format 0 (nr_tti_rx %d)\n",ue->Mod_id,nr_tti_rx); + #endif + ue->ulsch[eNB_id]->num_cba_dci[(nr_tti_rx+4)%10]++; + } + } + + else { + #ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] frame %d, nr_tti_rx %d: received DCI %d with RNTI=%x (C-RNTI:%x, CBA_RNTI %x) and format %d!\n",ue->Mod_id,frame_rx,nr_tti_rx,i,dci_alloc_rx[i].rnti, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + ue->ulsch[eNB_id]->cba_rnti[0], + dci_alloc_rx[i].format); + + // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + #endif + } +#endif //(0) + + + + } // end for loop dci_cnt +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_rx_pdcch_stats); +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); + + } // end if do_pdcch_monitoring_current_slot + } // end for loop nb_searchspacet_active + return(0); +} +#endif + +#if 0 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t abstraction_flag) +{ + + unsigned int dci_cnt=0, i; + + int frame_rx = proc->frame_rx; + int nr_tti_rx = proc->nr_tti_rx; + DCI_ALLOC_t dci_alloc_rx[8]; + + uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); + uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); + +#ifdef PHY_ABSTRACTION + int CC_id; + int UE_id; + uint8_t harq_pid; +#endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_IN); +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_rx_pdcch_stats); +#endif + + // if (nr_tti_rx != 5) + // return 0; + if (abstraction_flag == 0) { + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN); + rx_pdcch(ue, + proc->frame_rx, + nr_tti_rx, + eNB_id, + (ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, + ue->high_speed_flag, + ue->is_secondary_ue); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_IN); + + + //printf("Decode SIB frame param agregation + DCI %d %d \n",agregationLevel,dciFormat); + + //agregation level == FF means no configuration on + if(ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->agregationLevel == 0xFF || ue->decode_SIB) + { + // search all possible dcis + dci_cnt = dci_decoding_procedure(ue, + dci_alloc_rx, + (ue->UE_mode[eNB_id] < PUSCH)? 1 : 0, // if we're in PUSCH don't listen to common search space, + // later when we need paging or RA during connection, update this ... + eNB_id,nr_tti_rx); + } + else + { + // search only preconfigured dcis + // search C RNTI dci + dci_cnt = dci_CRNTI_decoding_procedure(ue, + dci_alloc_rx, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dciFormat, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->agregationLevel, + eNB_id, + nr_tti_rx); + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT); + //LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d PHICH RX\n",ue->Mod_id,frame_rx,nr_tti_rx); + + if (is_phich_subframe(&ue->frame_parms,nr_tti_rx)) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH, VCD_FUNCTION_IN); + rx_phich(ue,proc, + nr_tti_rx,eNB_id); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH, VCD_FUNCTION_OUT); + } + } + +#ifdef PHY_ABSTRACTION + else { + for (i=0; i<NB_eNB_INST; i++) { + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) + if (PHY_vars_eNB_g[i][CC_id]->frame_parms.Nid_cell == ue->frame_parms.Nid_cell) + break; + + if (CC_id < MAX_NUM_CCs) + break; + } + + if (i==NB_eNB_INST) { + LOG_E(PHY,"[UE %d] phy_procedures_lte_ue.c: FATAL : Could not find attached eNB for DCI emulation (Nid_cell %d)!!!!\n",ue->Mod_id,ue->frame_parms.Nid_cell); + //mac_xface->macphy_exit("Could not find attached eNB for DCI emulation"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); + return(-1); + } + + LOG_D(PHY,"Calling dci_decoding_proc_emul ...\n"); + dci_cnt = dci_decoding_procedure_emul(ue->pdcch_vars[nr_tti_rx&1], + PHY_vars_eNB_g[i][CC_id]->num_ue_spec_dci[nr_tti_rx&1], + PHY_vars_eNB_g[i][CC_id]->num_common_dci[nr_tti_rx&1], + PHY_vars_eNB_g[i][CC_id]->dci_alloc[nr_tti_rx&1], + dci_alloc_rx, + eNB_id); + // printf("DCI: dci_cnt %d\n",dci_cnt); + UE_id = (uint32_t)nr_find_ue((int16_t)ue->pdcch_vars[nr_tti_rx&1][eNB_id]->crnti,PHY_vars_eNB_g[i][CC_id]); + + if (UE_id>=0) { + // printf("Checking PHICH for UE %d (eNB %d)\n",UE_id,i); + if (is_phich_subframe(&ue->frame_parms,nr_tti_rx)) { + harq_pid = phich_subframe_to_harq_pid(&ue->frame_parms,frame_rx,nr_tti_rx); + + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == ACTIVE) { + // ue->ulsch[eNB_id]->harq_processes[harq_pid]->phich_ACK=1; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag =0; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->status = IDLE; + ue->ulsch_Msg3_active[eNB_id] = 0; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; + LOG_D(PHY,"Msg3 inactive\n"); + + } // harq_pid is ACTIVE + } // This is a PHICH nr_tti_rx + } // UE_id exists + } + +#endif + + uint8_t *nCCE_current = &ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->nCCE[nr_tti_rx]; + uint8_t *nCCE_dest = &ue->pdcch_vars[next1_thread_id][eNB_id]->nCCE[nr_tti_rx]; + uint8_t *nCCE_dest1 = &ue->pdcch_vars[next2_thread_id][eNB_id]->nCCE[nr_tti_rx]; + memcpy(nCCE_dest, nCCE_current, sizeof(uint8_t)); + memcpy(nCCE_dest1, nCCE_current, sizeof(uint8_t)); + + LOG_D(PHY,"current_thread %d next1_thread %d next2_thread %d \n", ue->current_thread_id[nr_tti_rx], next1_thread_id, next2_thread_id); + + LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d, Mode %s: DCI found %i --> rnti %x / crnti %x : format %d\n", + ue->Mod_id,frame_rx%1024,nr_tti_rx,mode_string[ue->UE_mode[eNB_id]], + dci_cnt, + dci_alloc_rx[0].rnti, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + dci_alloc_rx[0].format ); + + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dci_received += dci_cnt; + +#ifdef EMOS + //emos_dump_UE.dci_cnt[nr_tti_rx] = dci_cnt; +#endif + + for (i=0; i<dci_cnt; i++) { + + if ((ue->UE_mode[eNB_id]>PRACH) && + (dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && + (dci_alloc_rx[i].format != format0)) { + + LOG_D(PHY,"[UE %d][DCI][PDSCH %x] AbsSubframe %d.%d: format %d, num_pdcch_symbols %d, nCCE %d, total CCEs %d\n", + ue->Mod_id,dci_alloc_rx[i].rnti, + frame_rx%1024,nr_tti_rx, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->nCCE[nr_tti_rx], + get_nCCE(3,&ue->frame_parms,get_mi(&ue->frame_parms,0))); + + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + + if ((ue->UE_mode[eNB_id] > PRACH) && + (generate_ue_dlsch_params_from_dci(frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + ue->pdcch_vars[0%RX_NB_TH][eNB_id]->crnti_is_temporary? ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti: 0)==0)) { + + // update TPC for PUCCH + if((dci_alloc_rx[i].format == format1) || + (dci_alloc_rx[i].format == format1A) || + (dci_alloc_rx[i].format == format1B) || + (dci_alloc_rx[i].format == format2) || + (dci_alloc_rx[i].format == format2A) || + (dci_alloc_rx[i].format == format2B)) + { + //ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->g_pucch += ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid]->delta_PUCCH; + int32_t delta_pucch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid]->delta_PUCCH; + for(int th_id=0; th_id<RX_NB_TH; th_id++) + { + ue->dlsch[th_id][eNB_id][0]->g_pucch += delta_pucch; + } + LOG_D(PHY,"update TPC for PUCCH %d.%d / pid %d delta_PUCCH %d g_pucch %d %d \n",frame_rx, nr_tti_rx,ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid, + delta_pucch, + ue->dlsch[0][eNB_id][0]->g_pucch, + ue->dlsch[1][eNB_id][0]->g_pucch + //ue->dlsch[2][eNB_id][0]->g_pucch + ); + } + + ue->dlsch_received[eNB_id]++; + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Generated UE DLSCH C_RNTI format %d\n",ue->Mod_id,dci_alloc_rx[i].format); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + LOG_D(PHY,"[UE %d] *********** dlsch->active in nr_tti_rx %d=> %d\n",ue->Mod_id,nr_tti_rx,ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active); +#endif + + // we received a CRNTI, so we're in PUSCH + if (ue->UE_mode[eNB_id] != PUSCH) { +#ifdef DEBUG_PHY_PROC + LOG_I(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Received DCI with CRNTI %x => Mode PUSCH\n",ue->Mod_id,frame_rx,nr_tti_rx,ue->pdcch_vars[nr_tti_rx&1][eNB_id]->crnti); +#endif + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + ue->UE_mode[eNB_id] = PUSCH; + //mac_xface->macphy_exit("Connected. Exiting\n"); + } + } else { + LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Problem in DCI!\n",ue->Mod_id,frame_rx,nr_tti_rx); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + } + } + + else if ((dci_alloc_rx[i].rnti == SI_RNTI) && + ((dci_alloc_rx[i].format == format1A) || (dci_alloc_rx[i].format == format1C))) { + +#ifdef DEBUG_PHY_PROC + LOG_I(PHY,"[UE %d] nr_tti_rx %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,nr_tti_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); +#endif + + + if (generate_ue_dlsch_params_from_dci(frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + SI_RNTI, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars_SI[eNB_id], + &ue->dlsch_SI[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + 0)==0) { + + ue->dlsch_SI_received[eNB_id]++; + + + LOG_I(PHY,"[UE %d] Frame %d, nr_tti_rx %d : Generate UE DLSCH SI_RNTI format 1%s\n",ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].format==format1A?"A":"C"); + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + + } + } + + else if ((dci_alloc_rx[i].rnti == P_RNTI) && + ((dci_alloc_rx[i].format == format1A) || (dci_alloc_rx[i].format == format1C))) { + +#ifdef DEBUG_PHY_PROC + LOG_I(PHY,"[UE %d] nr_tti_rx %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,nr_tti_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); +#endif + + + if (generate_ue_dlsch_params_from_dci(frame_rx, + nr_tti_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + P_RNTI, + dci_alloc_rx[i].format, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars_p[eNB_id], + &ue->dlsch_SI[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + 0)==0) { + + ue->dlsch_p_received[eNB_id]++; + LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d : Generate UE DLSCH P_RNTI format 1%s\n",ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].format==format1A?"A":"C"); + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + + } + } + + else if ((ue->prach_resources[eNB_id]) && + (dci_alloc_rx[i].rnti == ue->prach_resources[eNB_id]->ra_RNTI) && + (dci_alloc_rx[i].format == format1A)) { + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][RAPROC] nr_tti_rx %d: Found RA rnti %x, format 1A, dci_cnt %d\n",ue->Mod_id,nr_tti_rx,dci_alloc_rx[i].rnti,i); + + //if (((frame_rx%100) == 0) || (frame_rx < 20)) + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + //mac_xface->macphy_exit("so far so good...\n"); +#endif + + + if (generate_ue_dlsch_params_from_dci(frame_rx, + nr_tti_rx, + (DCI1A_5MHz_TDD_1_6_t *)&dci_alloc_rx[i].dci_pdu, + ue->prach_resources[eNB_id]->ra_RNTI, + format1A, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], + ue->pdsch_vars_ra[eNB_id], + &ue->dlsch_ra[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + ue->prach_resources[eNB_id]->ra_RNTI, + P_RNTI, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], + 0)==0) { + + ue->dlsch_ra_received[eNB_id]++; + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Generate UE DLSCH RA_RNTI format 1A, rb_alloc %x, dlsch_ra[eNB_id] %p\n", + ue->Mod_id,ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even[0],ue->dlsch_ra[eNB_id]); +#endif + } + } else if( (dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && + (dci_alloc_rx[i].format == format0)) { + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d: Found rnti %x, format 0, dci_cnt %d\n", + ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].rnti,i); +#endif + + ue->ulsch_no_allocation_counter[eNB_id] = 0; + //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); + + if ((ue->UE_mode[eNB_id] > PRACH) && + (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + nr_tti_rx, + format0, + ue, + proc, + SI_RNTI, + 0, + P_RNTI, + CBA_RNTI, + eNB_id, + 0)==0)) { +#if T_TRACER + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + uint8_t harq_pid = nr_subframe2harq_pid(frame_parms, + nr_pdcch_alloc2ul_frame(frame_parms,proc->frame_rx,proc->nr_tti_rx), + nr_pdcch_alloc2ul_subframe(frame_parms,proc->nr_tti_rx)); + + T(T_UE_PHY_ULSCH_UE_DCI, T_INT(eNB_id), T_INT(proc->frame_rx%1024), T_INT(proc->nr_tti_rx), T_INT(ue->Mod_id), + T_INT(dci_alloc_rx[i].rnti), T_INT(harq_pid), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->round), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb), + T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS)); +#endif +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Generate UE ULSCH C_RNTI format 0 (nr_tti_rx %d)\n",ue->Mod_id,nr_tti_rx); +#endif + + } + } else if( (dci_alloc_rx[i].rnti == ue->ulsch[eNB_id]->cba_rnti[0]) && + (dci_alloc_rx[i].format == format0)) { + // UE could belong to more than one CBA group + // ue->Mod_id%ue->ulsch[eNB_id]->num_active_cba_groups] +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d: Found cba rnti %x, format 0, dci_cnt %d\n", + ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].rnti,i); + /* + if (((frame_rx%100) == 0) || (frame_rx < 20)) + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + */ +#endif + + ue->ulsch_no_allocation_counter[eNB_id] = 0; + //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); + + if ((ue->UE_mode[eNB_id] > PRACH) && + (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, + ue->ulsch[eNB_id]->cba_rnti[0], + nr_tti_rx, + format0, + ue, + proc, + SI_RNTI, + 0, + P_RNTI, + CBA_RNTI, + eNB_id, + 0)==0)) { + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Generate UE ULSCH CBA_RNTI format 0 (nr_tti_rx %d)\n",ue->Mod_id,nr_tti_rx); +#endif + ue->ulsch[eNB_id]->num_cba_dci[(nr_tti_rx+4)%10]++; + } + } + + else { +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] frame %d, nr_tti_rx %d: received DCI %d with RNTI=%x (C-RNTI:%x, CBA_RNTI %x) and format %d!\n",ue->Mod_id,frame_rx,nr_tti_rx,i,dci_alloc_rx[i].rnti, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + ue->ulsch[eNB_id]->cba_rnti[0], + dci_alloc_rx[i].format); + + // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); +#endif + } + + } +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_rx_pdcch_stats); +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); + return(0); +} + + + +void ue_pmch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc,int eNB_id,int abstraction_flag) { + + int nr_tti_rx = proc->nr_tti_rx; + int frame_rx = proc->frame_rx; + int pmch_mcs=-1; +#if defined(Rel10) || defined(Rel14) + int CC_id = ue->CC_id; +#endif + uint8_t sync_area=255; + uint8_t mcch_active; + int l; + int ret=0; + + if (is_pmch_subframe(frame_rx,nr_tti_rx,&ue->frame_parms)) { + LOG_D(PHY,"ue calling pmch nr_tti_rx ..\n "); + + LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Querying for PMCH demodulation\n", + ue->Mod_id,(nr_tti_rx==9?-1:0)+frame_rx,nr_tti_rx); +#if defined(Rel10) || defined(Rel14) + /*pmch_mcs = mac_xface->ue_query_mch(ue->Mod_id, + CC_id, + frame_rx, + nr_tti_rx, + eNB_id, + &sync_area, + &mcch_active);*/ + +#else + pmch_mcs=-1; +#endif + + if (pmch_mcs>=0) { + LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Programming PMCH demodulation for mcs %d\n",ue->Mod_id,frame_rx,nr_tti_rx,pmch_mcs); + fill_UE_dlsch_MCH(ue,pmch_mcs,1,0,0); + + if (abstraction_flag == 0 ) { + for (l=2; l<12; l++) { + + slot_fep_mbsfn(ue, + l, + nr_tti_rx, + 0,0);//ue->rx_offset,0); + } + + for (l=2; l<12; l++) { + rx_pmch(ue, + 0, + nr_tti_rx, + l); + } + + + ue->dlsch_MCH[0]->harq_processes[0]->G = get_G(&ue->frame_parms, + ue->dlsch_MCH[0]->harq_processes[0]->nb_rb, + ue->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even, + ue->dlsch_MCH[0]->harq_processes[0]->Qm, + 1, + 2, + frame_rx, + nr_tti_rx, + 0); + + dlsch_unscrambling(&ue->frame_parms,1,ue->dlsch_MCH[0], + ue->dlsch_MCH[0]->harq_processes[0]->G, + ue->pdsch_vars_MCH[0]->llr[0],0,nr_tti_rx<<1); + +#ifdef UE_DLSCH_PARALLELISATION + ret = dlsch_decoding_mthread(ue,proc, eNB_id, + ue->pdsch_vars_MCH[0]->llr[0], + &ue->frame_parms, + ue->dlsch_MCH[0], + ue->dlsch_MCH[0]->harq_processes[0], + frame_rx, + nr_tti_rx, + 0, + 0,1); +#else + ret = dlsch_decoding(ue, + ue->pdsch_vars_MCH[0]->llr[0], + &ue->frame_parms, + ue->dlsch_MCH[0], + ue->dlsch_MCH[0]->harq_processes[0], + frame_rx, + nr_tti_rx, + 0, + 0,1); + printf("start pmch dlsch decoding\n"); +#endif + } else { // abstraction +#ifdef PHY_ABSTRACTION + ret = dlsch_decoding_emul(ue, + nr_tti_rx, + 5, // PMCH + eNB_id); +#endif + } + + if (mcch_active == 1) + ue->dlsch_mcch_trials[sync_area][0]++; + else + ue->dlsch_mtch_trials[sync_area][0]++; + + if (ret == (1+ue->dlsch_MCH[0]->max_turbo_iterations)) { + if (mcch_active == 1) + ue->dlsch_mcch_errors[sync_area][0]++; + else + ue->dlsch_mtch_errors[sync_area][0]++; + + LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: PMCH in error (%d,%d), not passing to L2 (TBS %d, iter %d,G %d)\n", + ue->Mod_id, + frame_rx,nr_tti_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); + dump_mch(ue,0,ue->dlsch_MCH[0]->harq_processes[0]->G,nr_tti_rx); +#ifdef DEBUG_DLSCH + + for (int i=0; i<ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3; i++) { + LOG_T(PHY,"%02x.",ue->dlsch_MCH[0]->harq_processes[0]->c[0][i]); + } + + LOG_T(PHY,"\n"); +#endif + + if (nr_tti_rx==9) + //mac_xface->macphy_exit("Why are we exiting here?"); + } else { // decoding successful +#if defined(Rel10) || defined(Rel14) + + if (mcch_active == 1) { + /*mac_xface->ue_send_mch_sdu(ue->Mod_id, + CC_id, + frame_rx, + ue->dlsch_MCH[0]->harq_processes[0]->b, + ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, + eNB_id,// not relevant in eMBMS context + sync_area);*/ + ue->dlsch_mcch_received[sync_area][0]++; + + + if (ue->dlsch_mch_received_sf[nr_tti_rx%5][0] == 1 ) { + ue->dlsch_mch_received_sf[nr_tti_rx%5][0]=0; + } else { + ue->dlsch_mch_received[0]+=1; + ue->dlsch_mch_received_sf[nr_tti_rx][0]=1; + } + + + } +#endif // Rel10 || Rel14 + } // decoding sucessful + } // pmch_mcs>=0 + } // is_pmch_subframe=true +} + +void copy_harq_proc_struct(NR_DL_UE_HARQ_t *harq_processes_dest, NR_DL_UE_HARQ_t *current_harq_processes) +{ + harq_processes_dest->B = current_harq_processes->B ; + harq_processes_dest->C = current_harq_processes->C ; + harq_processes_dest->Cminus = current_harq_processes->Cminus ; + harq_processes_dest->Cplus = current_harq_processes->Cplus ; + harq_processes_dest->DCINdi = current_harq_processes->DCINdi ; + harq_processes_dest->F = current_harq_processes->F ; + harq_processes_dest->G = current_harq_processes->G ; + harq_processes_dest->Kminus = current_harq_processes->Kminus ; + harq_processes_dest->Kplus = current_harq_processes->Kplus ; + harq_processes_dest->Nl = current_harq_processes->Nl ; + harq_processes_dest->Qm = current_harq_processes->Qm ; + harq_processes_dest->TBS = current_harq_processes->TBS ; + harq_processes_dest->b = current_harq_processes->b ; + harq_processes_dest->codeword = current_harq_processes->codeword ; + harq_processes_dest->delta_PUCCH = current_harq_processes->delta_PUCCH ; + harq_processes_dest->dl_power_off = current_harq_processes->dl_power_off ; + harq_processes_dest->first_tx = current_harq_processes->first_tx ; + harq_processes_dest->mcs = current_harq_processes->mcs ; + harq_processes_dest->mimo_mode = current_harq_processes->mimo_mode ; + harq_processes_dest->nb_rb = current_harq_processes->nb_rb ; + harq_processes_dest->pmi_alloc = current_harq_processes->pmi_alloc ; + harq_processes_dest->rb_alloc_even[0] = current_harq_processes->rb_alloc_even[0] ; + harq_processes_dest->rb_alloc_even[1] = current_harq_processes->rb_alloc_even[1] ; + harq_processes_dest->rb_alloc_even[2] = current_harq_processes->rb_alloc_even[2] ; + harq_processes_dest->rb_alloc_even[3] = current_harq_processes->rb_alloc_even[3] ; + harq_processes_dest->rb_alloc_odd[0] = current_harq_processes->rb_alloc_odd[0] ; + harq_processes_dest->rb_alloc_odd[1] = current_harq_processes->rb_alloc_odd[1] ; + harq_processes_dest->rb_alloc_odd[2] = current_harq_processes->rb_alloc_odd[2] ; + harq_processes_dest->rb_alloc_odd[3] = current_harq_processes->rb_alloc_odd[3] ; + harq_processes_dest->round = current_harq_processes->round ; + harq_processes_dest->rvidx = current_harq_processes->rvidx ; + harq_processes_dest->status = current_harq_processes->status ; + harq_processes_dest->vrb_type = current_harq_processes->vrb_type ; +} + +void copy_ack_struct(nr_harq_status_t *harq_ack_dest, nr_harq_status_t *current_harq_ack) +{ + memcpy(harq_ack_dest, current_harq_ack, sizeof(nr_harq_status_t)); +} + +void ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_id, PDSCH_t pdsch, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1, int s0, int s1, int abstraction_flag) { + + int nr_tti_rx = proc->nr_tti_rx; + int m; + int harq_pid; + int i_mod,eNB_id_i,dual_stream_UE; + int first_symbol_flag=0; + + if (dlsch0->active == 0) + return; + + for (m=s0;m<=s1;m++) { + + if (dlsch0 && (!dlsch1)) { + harq_pid = dlsch0->current_harq_pid; + LOG_D(PHY,"[UE %d] PDSCH active in nr_tti_rx %d, harq_pid %d Symbol %d\n",ue->Mod_id,nr_tti_rx,harq_pid,m); + + if ((pdsch==PDSCH) && + (ue->transmission_mode[eNB_id] == 5) && + (dlsch0->harq_processes[harq_pid]->dl_power_off==0) && + (ue->use_ia_receiver ==1)) { + dual_stream_UE = 1; + eNB_id_i = ue->n_connected_eNB; + i_mod = dlsch0->harq_processes[harq_pid]->Qm; + + } + else if((pdsch==PDSCH) && (ue->transmission_mode[eNB_id]==3)) + { + dual_stream_UE = rx_IC_dual_stream; + eNB_id_i = eNB_id; + i_mod = 0; + } + else { + dual_stream_UE = 0; + eNB_id_i = eNB_id+1; + i_mod = 0; + } + + //TM7 UE specific channel estimation here!!! + if (ue->transmission_mode[eNB_id]==7) { + if (ue->frame_parms.Ncp==0) { + if ((m==3) || (m==6) || (m==9) || (m==12)) + //LOG_D(PHY,"[UE %d] dlsch->active in nr_tti_rx %d => %d, l=%d\n",phy_vars_ue->Mod_id,nr_tti_rx,phy_vars_ue->dlsch_ue[eNB_id][0]->active, l); + lte_dl_bf_channel_estimation(ue,eNB_id,0,nr_tti_rx*2+(m>6?1:0),5,m); + } else { + LOG_E(PHY,"[UE %d]Beamforming channel estimation not supported yet for TM7 extented CP.\n",ue->Mod_id); + } + } + + if ((m==s0) && (m<4)) + first_symbol_flag = 1; + else + first_symbol_flag = 0; +#if UE_TIMING_TRACE + uint8_t slot = 0; + if(m >= ue->frame_parms.symbols_per_tti>>1) + slot = 1; + start_meas(&ue->dlsch_llr_stats_parallelization[ue->current_thread_id[nr_tti_rx]][slot]); +#endif + // process DLSCH received in first slot + rx_pdsch(ue, + pdsch, + eNB_id, + eNB_id_i, + proc->frame_rx, + nr_tti_rx, // nr_tti_rx, + m, + first_symbol_flag, + dual_stream_UE, + i_mod, + dlsch0->current_harq_pid); +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_llr_stats_parallelization[ue->current_thread_id[nr_tti_rx]][slot]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",proc->frame_rx,nr_tti_rx,m,ue->dlsch_llr_stats_parallelization[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",proc->frame_rx,nr_tti_rx,m,ue->dlsch_llr_stats_parallelization[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); +#endif +#endif + + + if(first_symbol_flag) + { + proc->first_symbol_available = 1; + } + } // CRNTI active + } +} + +void process_rar(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_id, runmode_t mode, int abstraction_flag) { + + int frame_rx = proc->frame_rx; + int nr_tti_rx = proc->nr_tti_rx; + int timing_advance; + NR_UE_DLSCH_t *dlsch0 = ue->dlsch_ra[eNB_id]; + int harq_pid = 0; + uint8_t *rar; + uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); + uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); + + LOG_D(PHY,"[UE %d][RAPROC] Frame %d nr_tti_rx %d Received RAR mode %d\n", + ue->Mod_id, + frame_rx, + nr_tti_rx, ue->UE_mode[eNB_id]); + + + if (ue->mac_enabled == 1) { + if ((ue->UE_mode[eNB_id] != PUSCH) && + (ue->prach_resources[eNB_id]->Msg3!=NULL)) { + LOG_D(PHY,"[UE %d][RAPROC] Frame %d nr_tti_rx %d Invoking MAC for RAR (current preamble %d)\n", + ue->Mod_id,frame_rx, + nr_tti_rx, + ue->prach_resources[eNB_id]->ra_PreambleIndex); + +/* timing_advance = mac_xface->ue_process_rar(ue->Mod_id, + ue->CC_id, + frame_rx, + ue->prach_resources[eNB_id]->ra_RNTI, + dlsch0->harq_processes[0]->b, + &ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + ue->prach_resources[eNB_id]->ra_PreambleIndex, + dlsch0->harq_processes[0]->b); // alter the 'b' buffer so it contains only the selected RAR header and RAR payload +*/ + ue->pdcch_vars[next1_thread_id][eNB_id]->crnti = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti; + ue->pdcch_vars[next2_thread_id][eNB_id]->crnti = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti; + + if (timing_advance!=0xffff) { + + LOG_D(PHY,"[UE %d][RAPROC] Frame %d nr_tti_rx %d Got rnti %x and timing advance %d from RAR\n", + ue->Mod_id, + frame_rx, + nr_tti_rx, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, + timing_advance); + + // remember this c-rnti is still a tc-rnti + + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti_is_temporary = 1; + + //timing_advance = 0; + nr_process_timing_advance_rar(ue,proc,timing_advance); + + if (mode!=debug_prach) { + ue->ulsch_Msg3_active[eNB_id]=1; + nr_get_Msg3_alloc(&ue->frame_parms, + nr_tti_rx, + frame_rx, + &ue->ulsch_Msg3_frame[eNB_id], + &ue->ulsch_Msg3_subframe[eNB_id]); + + LOG_D(PHY,"[UE %d][RAPROC] Got Msg3_alloc Frame %d nr_tti_rx %d: Msg3_frame %d, Msg3_subframe %d\n", + ue->Mod_id, + frame_rx, + nr_tti_rx, + ue->ulsch_Msg3_frame[eNB_id], + ue->ulsch_Msg3_subframe[eNB_id]); + harq_pid = nr_subframe2harq_pid(&ue->frame_parms, + ue->ulsch_Msg3_frame[eNB_id], + ue->ulsch_Msg3_subframe[eNB_id]); + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; + + ue->UE_mode[eNB_id] = RA_RESPONSE; + // ue->Msg3_timer[eNB_id] = 10; + ue->ulsch[eNB_id]->power_offset = 6; + ue->ulsch_no_allocation_counter[eNB_id] = 0; + } + } else { // PRACH preamble doesn't match RAR + LOG_W(PHY,"[UE %d][RAPROC] Received RAR preamble (%d) doesn't match !!!\n", + ue->Mod_id, + ue->prach_resources[eNB_id]->ra_PreambleIndex); + } + } // mode != PUSCH + } + else { + rar = dlsch0->harq_processes[0]->b+1; + timing_advance = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); + nr_process_timing_advance_rar(ue,proc,timing_advance); + } + +} + +void ue_dlsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int eNB_id, + PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + int *dlsch_errors, + runmode_t mode, + int abstraction_flag) { + + int harq_pid; + int frame_rx = proc->frame_rx; + int nr_tti_rx = proc->nr_tti_rx; + int ret=0, ret1=0; + int CC_id = ue->CC_id; + NR_UE_PDSCH *pdsch_vars; + uint8_t is_cw0_active = 0; + uint8_t is_cw1_active = 0; + + if (dlsch0==NULL) + AssertFatal(0,"dlsch0 should be defined at this level \n"); + + harq_pid = dlsch0->current_harq_pid; + is_cw0_active = dlsch0->harq_processes[harq_pid]->status; + + if(dlsch1) + is_cw1_active = dlsch1->harq_processes[harq_pid]->status; + + LOG_D(PHY,"AbsSubframe %d.%d Start Turbo Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx%1024, nr_tti_rx, harq_pid, is_cw0_active); + LOG_D(PHY,"AbsSubframe %d.%d Start Turbo Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx%1024, nr_tti_rx, harq_pid, is_cw1_active); + + if(is_cw0_active && is_cw1_active) + { + dlsch0->Kmimo = 2; + dlsch1->Kmimo = 2; + } + else + { + dlsch0->Kmimo = 1; + } + if (1) { + switch (pdsch) { + case SI_PDSCH: + pdsch_vars = ue->pdsch_vars_SI[eNB_id]; + break; + case RA_PDSCH: + pdsch_vars = ue->pdsch_vars_ra[eNB_id]; + break; + case P_PDSCH: + pdsch_vars = ue->pdsch_vars_p[eNB_id]; + break; + case PDSCH: + pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; + break; + case PMCH: + case PDSCH1: + LOG_E(PHY,"Illegal PDSCH %d for ue_pdsch_procedures\n",pdsch); + pdsch_vars = NULL; + return; + break; + default: + pdsch_vars = NULL; + return; + break; + + } + if (frame_rx < *dlsch_errors) + *dlsch_errors=0; + + if (pdsch==RA_PDSCH) { + if (ue->prach_resources[eNB_id]!=NULL) + dlsch0->rnti = ue->prach_resources[eNB_id]->ra_RNTI; + else { + LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d: FATAL, prach_resources is NULL\n",ue->Mod_id,frame_rx,nr_tti_rx); + //mac_xface->macphy_exit("prach_resources is NULL"); + return; + } + } + + if (abstraction_flag == 0) { + + // start turbo decode for CW 0 + dlsch0->harq_processes[harq_pid]->G = get_G(&ue->frame_parms, + dlsch0->harq_processes[harq_pid]->nb_rb, + dlsch0->harq_processes[harq_pid]->rb_alloc_even, + dlsch0->harq_processes[harq_pid]->Qm, + dlsch0->harq_processes[harq_pid]->Nl, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + frame_rx, + nr_tti_rx, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]); +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_unscrambling_stats); +#endif + dlsch_unscrambling(&ue->frame_parms, + 0, + dlsch0, + dlsch0->harq_processes[harq_pid]->G, + pdsch_vars->llr[0], + 0, + nr_tti_rx<<1); +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_unscrambling_stats); +#endif + +#if 0 + LOG_I(PHY," ------ start turbo decoder for AbsSubframe %d.%d / %d ------ \n", frame_rx, nr_tti_rx, harq_pid); + LOG_I(PHY,"start turbo decode for CW 0 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->nb_rb); + LOG_I(PHY,"start turbo decode for CW 0 for AbsSubframe %d.%d / %d --> rb_alloc_even %x \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->rb_alloc_even); + LOG_I(PHY,"start turbo decode for CW 0 for AbsSubframe %d.%d / %d --> Qm %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Qm); + LOG_I(PHY,"start turbo decode for CW 0 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Nl); + LOG_I(PHY,"start turbo decode for CW 0 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->G); + LOG_I(PHY,"start turbo decode for CW 0 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->Kmimo); + LOG_I(PHY,"start turbo decode for CW 0 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_tti_rx, harq_pid, ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols); +#endif + +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]]); +#endif + +#ifdef UE_DLSCH_PARALLELISATION + ret = dlsch_decoding_mthread(ue,proc,eNB_id, + pdsch_vars->llr[0], + &ue->frame_parms, + dlsch0, + dlsch0->harq_processes[harq_pid], + frame_rx, + nr_tti_rx, + harq_pid, + pdsch==PDSCH?1:0, + dlsch0->harq_processes[harq_pid]->TBS>256?1:0); +#else + ret = dlsch_decoding(ue, + pdsch_vars->llr[0], + &ue->frame_parms, + dlsch0, + dlsch0->harq_processes[harq_pid], + frame_rx, + nr_tti_rx, + harq_pid, + pdsch==PDSCH?1:0,//proc->decoder_switch, + dlsch0->harq_processes[harq_pid]->TBS>256?1:0); + //printf("start cW0 dlsch decoding\n"); +#endif + +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf(" --> Unscrambling for CW0 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + printf("AbsSubframe %d.%d --> Turbo Decoding for CW0 %5.3f\n", + frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); +#else + LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + LOG_I(PHY, "AbsSubframe %d.%d --> Turbo Decoding for CW0 %5.3f\n", + frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); +#endif + +#endif + if(is_cw1_active) + { + // start turbo decode for CW 1 + dlsch1->harq_processes[harq_pid]->G = get_G(&ue->frame_parms, + dlsch1->harq_processes[harq_pid]->nb_rb, + dlsch1->harq_processes[harq_pid]->rb_alloc_even, + dlsch1->harq_processes[harq_pid]->Qm, + dlsch1->harq_processes[harq_pid]->Nl, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + frame_rx, + nr_tti_rx, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]); +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_unscrambling_stats); +#endif + dlsch_unscrambling(&ue->frame_parms, + 0, + dlsch1, + dlsch1->harq_processes[harq_pid]->G, + pdsch_vars->llr[1], + 1, + nr_tti_rx<<1); +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_unscrambling_stats); +#endif + +#if 0 + LOG_I(PHY,"start turbo decode for CW 1 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->nb_rb); + LOG_I(PHY,"start turbo decode for CW 1 for AbsSubframe %d.%d / %d --> rb_alloc_even %x \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->rb_alloc_even); + LOG_I(PHY,"start turbo decode for CW 1 for AbsSubframe %d.%d / %d --> Qm %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Qm); + LOG_I(PHY,"start turbo decode for CW 1 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Nl); + LOG_I(PHY,"start turbo decode for CW 1 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->G); + LOG_I(PHY,"start turbo decode for CW 1 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->Kmimo); + LOG_I(PHY,"start turbo decode for CW 1 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_tti_rx, harq_pid, ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols); +#endif + +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]]); +#endif + +#ifdef UE_DLSCH_PARALLELISATION + ret1 = dlsch_decoding_mthread(ue,proc, eNB_id, + pdsch_vars->llr[1], + &ue->frame_parms, + dlsch1, + dlsch1->harq_processes[harq_pid], + frame_rx, + nr_tti_rx, + harq_pid, + pdsch==PDSCH?1:0, + dlsch1->harq_processes[harq_pid]->TBS>256?1:0); +#else + + ret1 = dlsch_decoding(ue, + pdsch_vars->llr[1], + &ue->frame_parms, + dlsch1, + dlsch1->harq_processes[harq_pid], + frame_rx, + nr_tti_rx, + harq_pid, + pdsch==PDSCH?1:0,//proc->decoder_switch, + dlsch1->harq_processes[harq_pid]->TBS>256?1:0); + printf("start cw1 dlsch decoding\n"); +#endif + +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf(" --> Unscrambling for CW1 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + printf("AbsSubframe %d.%d --> Turbo Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); +#else + LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + LOG_D(PHY, "AbsSubframe %d.%d --> Turbo Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); +#endif + +#endif + LOG_I(PHY,"AbsSubframe %d.%d --> Turbo Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); + } + + LOG_D(PHY," ------ end turbo decoder for AbsSubframe %d.%d ------ \n", frame_rx, nr_tti_rx); + } + + else { + LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); +#ifdef PHY_ABSTRACTION + ret = dlsch_decoding_emul(ue, + nr_tti_rx, + pdsch, + eNB_id); +#endif + } + + // Check CRC for CW 0 + if (ret == (1+dlsch0->max_turbo_iterations)) { + *dlsch_errors=*dlsch_errors+1; + + if(dlsch0->rnti != 0xffff) + { + LOG_D(PHY,"[UE %d][PDSCH %x/%d] AbsSubframe %d.%d : DLSCH CW0 in error (rv %d,round %d, mcs %d,TBS %d)\n", + ue->Mod_id,dlsch0->rnti, + harq_pid,frame_rx,nr_tti_rx, + dlsch0->harq_processes[harq_pid]->rvidx, + dlsch0->harq_processes[harq_pid]->round, + dlsch0->harq_processes[harq_pid]->mcs, + dlsch0->harq_processes[harq_pid]->TBS); + } + + + } else { + if(dlsch0->rnti != 0xffff) + { + LOG_D(PHY,"[UE %d][PDSCH %x/%d] AbsSubframe %d.%d : Received DLSCH CW0 (rv %d,round %d, mcs %d,TBS %d)\n", + ue->Mod_id,dlsch0->rnti, + harq_pid,frame_rx,nr_tti_rx, + dlsch0->harq_processes[harq_pid]->rvidx, + dlsch0->harq_processes[harq_pid]->round, + dlsch0->harq_processes[harq_pid]->mcs, + dlsch0->harq_processes[harq_pid]->TBS); + } + +#ifdef DEBUG_DLSCH + int j; + LOG_D(PHY,"dlsch harq_pid %d (rx): \n",dlsch0->current_harq_pid); + + for (j=0; j<dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS>>3; j++) + LOG_T(PHY,"%x.",dlsch0->harq_processes[dlsch0->current_harq_pid]->b[j]); + + LOG_T(PHY,"\n"); +#endif + + + switch (pdsch) { + case PDSCH: + if (ue->mac_enabled == 1) + //mac_xface->ue_send_sdu(ue->Mod_id, + CC_id, + frame_rx, + nr_tti_rx, + dlsch0->harq_processes[dlsch0->current_harq_pid]->b, + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS>>3, + eNB_id); + break; + case SI_PDSCH: + //mac_xface->ue_decode_si(ue->Mod_id, + CC_id, + frame_rx, + eNB_id, + ue->dlsch_SI[eNB_id]->harq_processes[0]->b, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); + break; + case P_PDSCH: + if (ue->mac_enabled == 1) + //mac_xface->ue_decode_p(ue->Mod_id, + CC_id, + frame_rx, + eNB_id, + ue->dlsch_SI[eNB_id]->harq_processes[0]->b, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); + break; + case RA_PDSCH: + if (ue->mac_enabled == 1) + process_rar(ue,proc,eNB_id,mode,abstraction_flag); + break; + case PDSCH1: + LOG_E(PHY,"Shouldn't have PDSCH1 yet, come back later\n"); + AssertFatal(1==0,"exiting"); + break; + case PMCH: + LOG_E(PHY,"Shouldn't have PMCH here\n"); + AssertFatal(1==0,"exiting"); + break; + + } + ue->total_TBS[eNB_id] = ue->total_TBS[eNB_id] + + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; + ue->total_received_bits[eNB_id] = ue->total_TBS[eNB_id] + + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; + } + // Check CRC for CW 1 + if(is_cw1_active) + { + if (ret1 == (1+dlsch0->max_turbo_iterations)) { + LOG_I(PHY,"[UE %d][PDSCH %x/%d] Frame %d nr_tti_rx %d DLSCH CW1 in error (rv %d,mcs %d,TBS %d)\n", + ue->Mod_id,dlsch0->rnti, + harq_pid,frame_rx,nr_tti_rx, + dlsch0->harq_processes[harq_pid]->rvidx, + dlsch0->harq_processes[harq_pid]->mcs, + dlsch0->harq_processes[harq_pid]->TBS); + + } else { + LOG_I(PHY,"[UE %d][PDSCH %x/%d] Frame %d nr_tti_rx %d: Received DLSCH CW1 (rv %d,mcs %d,TBS %d)\n", + ue->Mod_id,dlsch0->rnti, + harq_pid,frame_rx,nr_tti_rx, + dlsch0->harq_processes[harq_pid]->rvidx, + dlsch0->harq_processes[harq_pid]->mcs, + dlsch0->harq_processes[harq_pid]->TBS); + + + if (ue->mac_enabled == 1) { + switch (pdsch) { + case PDSCH: + if(is_cw1_active) + /*mac_xface->ue_send_sdu(ue->Mod_id, + CC_id, + frame_rx, + nr_tti_rx, + dlsch1->harq_processes[dlsch1->current_harq_pid]->b, + dlsch1->harq_processes[dlsch1->current_harq_pid]->TBS>>3, + eNB_id);*/ + break; + case SI_PDSCH: + case P_PDSCH: + case RA_PDSCH: + case PDSCH1: + case PMCH: + AssertFatal(0,"exiting"); + break; + } + } + } + } + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d nr_tti_rx %d: PDSCH/DLSCH decoding iter %d (mcs %d, rv %d, TBS %d)\n", + ue->Mod_id, + dlsch0->rnti,harq_pid, + frame_rx,nr_tti_rx,ret, + dlsch0->harq_processes[harq_pid]->mcs, + dlsch0->harq_processes[harq_pid]->rvidx, + dlsch0->harq_processes[harq_pid]->TBS); + + if (frame_rx%100==0) { + LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d nr_tti_rx %d dlsch_errors %d, dlsch_received %d, dlsch_fer %d, current_dlsch_cqi %d\n", + ue->Mod_id,dlsch0->rnti, + frame_rx,nr_tti_rx, + ue->dlsch_errors[eNB_id], + ue->dlsch_received[eNB_id], + ue->dlsch_fer[eNB_id], + ue->measurements.wideband_cqi_tot[eNB_id]); + } + +#endif + + } + + +} + +/*! + * \brief This is the UE synchronize thread. + * It performs band scanning and synchonization. + * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +#ifdef UE_SLOT_PARALLELISATION +#define FIFO_PRIORITY 40 +void *UE_thread_slot1_dl_processing(void *arg) { + + static __thread int UE_dl_slot1_processing_retval; + struct rx_tx_thread_data *rtd = arg; + UE_nr_rxtx_proc_t *proc = rtd->proc; + PHY_VARS_NR_UE *ue = rtd->UE; + + int frame_rx; + uint8_t nr_tti_rx; + uint8_t pilot0; + uint8_t pilot1; + uint8_t slot1; + + uint8_t next_nr_tti_rx; + uint8_t next_subframe_slot0; + + proc->instance_cnt_slot1_dl_processing=-1; + proc->nr_tti_rx=proc->sub_frame_start; + + char threadname[256]; + sprintf(threadname,"UE_thread_slot1_dl_processing_%d", proc->sub_frame_start); + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.slot1_proc_one != -1 ) + CPU_SET(threads.slot1_proc_one, &cpuset); + if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 ) + CPU_SET(threads.slot1_proc_two, &cpuset); + if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 ) + CPU_SET(threads.slot1_proc_three, &cpuset); + + init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, + threadname); + + while (!oai_exit) { + if (pthread_mutex_lock(&proc->mutex_slot1_dl_processing) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE slot1 dl processing\n" ); + exit_fun("nothing to add"); + } + while (proc->instance_cnt_slot1_dl_processing < 0) { + // most of the time, the thread is waiting here + pthread_cond_wait( &proc->cond_slot1_dl_processing, &proc->mutex_slot1_dl_processing ); + } + if (pthread_mutex_unlock(&proc->mutex_slot1_dl_processing) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE slot1 dl processing \n" ); + exit_fun("nothing to add"); + } + + /*for(int th_idx=0; th_idx< RX_NB_TH; th_idx++) + { + frame_rx = ue->proc.proc_rxtx[0].frame_rx; + nr_tti_rx = ue->proc.proc_rxtx[0].nr_tti_rx; + printf("AbsSubframe %d.%d execute dl slot1 processing \n", frame_rx, nr_tti_rx); + }*/ + frame_rx = proc->frame_rx; + nr_tti_rx = proc->nr_tti_rx; + next_nr_tti_rx = (1+nr_tti_rx)%10; + next_subframe_slot0 = next_nr_tti_rx<<1; + + slot1 = (nr_tti_rx<<1) + 1; + pilot0 = 0; + + //printf("AbsSubframe %d.%d execute dl slot1 processing \n", frame_rx, nr_tti_rx); + + if (ue->frame_parms.Ncp == 0) { // normal prefix + pilot1 = 4; + } else { // extended prefix + pilot1 = 3; + } + + /**** Slot1 FE Processing ****/ +#if UE_TIMING_TRACE + start_meas(&ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1]); +#endif + // I- start dl slot1 processing + // do first symbol of next downlink nr_tti_rx for channel estimation + /* + // 1- perform FFT for pilot ofdm symbols first (ofdmSym0 next nr_tti_rx ofdmSym11) + if (nr_subframe_select(&ue->frame_parms,next_nr_tti_rx) != SF_UL) + { + front_end_fft(ue, + pilot0, + next_subframe_slot0, + 0, + 0); + } + + front_end_fft(ue, + pilot1, + slot1, + 0, + 0); + */ + // 1- perform FFT + for (int l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) + { + //if( (l != pilot0) && (l != pilot1)) + { +#if UE_TIMING_TRACE + start_meas(&ue->ofdm_demod_stats); +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); + //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot1,l); + front_end_fft(ue, + l, + slot1, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&ue->ofdm_demod_stats); +#endif + } + } // for l=1..l2 + + if (nr_subframe_select(&ue->frame_parms,next_nr_tti_rx) != SF_UL) + { + //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_tti_rx,next_subframe_slot0,pilot0); + front_end_fft(ue, + pilot0, + next_subframe_slot0, + 0, + 0); + } + + // 2- perform Channel Estimation for slot1 + for (int l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) + { + if(l == pilot1) + { + //wait until channel estimation for pilot0/slot1 is available + uint32_t wait = 0; + while(proc->chan_est_pilot0_slot1_available == 0) + { + usleep(1); + wait++; + } + //printf("[slot1 dl processing] ChanEst symbol %d slot %d wait%d\n",l,slot1,wait); + } + //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot1,l); + front_end_chanEst(ue, + l, + slot1, + 0); + ue_measurement_procedures(l-1,ue,proc,0,1+(nr_tti_rx<<1),0,ue->mode); + } + //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_tti_rx,next_subframe_slot0,pilot0); + front_end_chanEst(ue, + pilot0, + next_subframe_slot0, + 0); + + if ( (nr_tti_rx == 0) && (ue->decode_MIB == 1)) + { + ue_pbch_procedures(0,ue,proc,0); + } + + proc->chan_est_slot1_available = 1; + //printf("Set available slot 1channelEst to 1 AbsSubframe %d.%d \n",frame_rx,nr_tti_rx); + //printf(" [slot1 dl processing] ==> FFT/CHanEst Done for AbsSubframe %d.%d \n", proc->frame_rx, proc->nr_tti_rx); + + //printf(" [slot1 dl processing] ==> Start LLR Comuptation slot1 for AbsSubframe %d.%d \n", proc->frame_rx, proc->nr_tti_rx); + + +#if UE_TIMING_TRACE + stop_meas(&ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_tti_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_tti_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1].p_time/(cpuf*1000.0)); +#endif +#endif + + + //wait until pdcch is decoded + uint32_t wait = 0; + while(proc->dci_slot0_available == 0) + { + usleep(1); + wait++; + } + //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait DCI %d\n",frame_rx,nr_tti_rx,wait); + + + /**** Pdsch Procedure Slot1 ****/ + // start slot1 thread for Pdsch Procedure (slot1) + // do procedures for C-RNTI + //printf("AbsSubframe %d.%d Pdsch Procedure (slot1)\n",frame_rx,nr_tti_rx); + + +#if UE_TIMING_TRACE + start_meas(&ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1]); +#endif + // start slave thread for Pdsch Procedure (slot1) + // do procedures for C-RNTI + uint8_t eNB_id = 0; + uint8_t abstraction_flag = 0; + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { + //wait until first ofdm symbol is processed + //wait = 0; + //while(proc->first_symbol_available == 0) + //{ + // usleep(1); + // wait++; + //} + //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait First Ofdm Sym %d\n",frame_rx,nr_tti_rx,wait); + + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], + NULL, + (ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + LOG_D(PHY," ------ --> PDSCH Turbo Decoder slot 0/1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + (ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + } + + // do procedures for P-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + (ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + } + // do procedures for RA-RNTI + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + (ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + } + + proc->llr_slot1_available=1; + //printf("Set available LLR slot1 to 1 AbsSubframe %d.%d \n",frame_rx,nr_tti_rx); + +#if UE_TIMING_TRACE + stop_meas(&ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_tti_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_tti_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1].p_time/(cpuf*1000.0)); +#endif +#endif + + + if (pthread_mutex_lock(&proc->mutex_slot1_dl_processing) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); + exit_fun("noting to add"); + } + proc->instance_cnt_slot1_dl_processing--; + if (pthread_mutex_unlock(&proc->mutex_slot1_dl_processing) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE FEP Slo1\n" ); + exit_fun("noting to add"); + } + } + // thread finished + free(arg); + return &UE_dl_slot1_processing_retval; +} +#endif + +#ifdef UE_SLOT_PARALLELISATION +int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id, + uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode, + relaying_type_t r_type) { + + int l,l2; + int pmch_flag=0; + int frame_rx = proc->frame_rx; + int nr_tti_rx = proc->nr_tti_rx; + uint8_t pilot0; + uint8_t pilot1; + uint8_t slot0; + uint8_t slot1; + uint8_t first_ofdm_sym; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); + +#if T_TRACER + T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_tti_rx)); + + T(T_UE_PHY_INPUT_SIGNAL, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_tti_rx), T_INT(0), + T_BUFFER(&ue->common_vars.rxdata[0][nr_tti_rx*ue->frame_parms.samples_per_subframe], + ue->frame_parms.samples_per_subframe * 4)); +#endif + + // start timers +#ifdef UE_DEBUG_TRACE + LOG_I(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); +#endif + +#if UE_TIMING_TRACE + start_meas(&ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]]); + start_meas(&ue->ue_front_end_stat[ue->current_thread_id[nr_tti_rx]]); +#endif + + pmch_flag = is_pmch_subframe(frame_rx,nr_tti_rx,&ue->frame_parms) ? 1 : 0; + + if (do_pdcch_flag) { + // deactivate reception until we scan pdcch + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]) + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 0; + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1]) + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1]->active = 0; + + if (ue->dlsch_SI[eNB_id]) + ue->dlsch_SI[eNB_id]->active = 0; + if (ue->dlsch_p[eNB_id]) + ue->dlsch_p[eNB_id]->active = 0; + if (ue->dlsch_ra[eNB_id]) + ue->dlsch_ra[eNB_id]->active = 0; + } + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[%s %d] Frame %d nr_tti_rx %d: Doing phy_procedures_UE_RX\n", + (r_type == multicast_relay) ? "RN/UE" : "UE", + ue->Mod_id,frame_rx, nr_tti_rx); +#endif + + + + + if (nr_subframe_select(&ue->frame_parms,nr_tti_rx) == SF_S) { // S-subframe, do first 5 symbols only + l2 = 5; + } else if (pmch_flag == 1) { // do first 2 symbols only + l2 = 1; + } else { // normal nr_tti_rx, last symbol to be processed is the first of the second slot + l2 = (ue->frame_parms.symbols_per_tti/2)-1; + } + + int prev_nr_tti_rx = (nr_tti_rx - 1)<0? 9: (nr_tti_rx - 1); + if (nr_subframe_select(&ue->frame_parms,prev_nr_tti_rx) != SF_DL) { + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // RX processing of symbols l=0...l2 + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + first_ofdm_sym = 0; + } else { + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch) + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + first_ofdm_sym = 1; + } + slot0 = (nr_tti_rx<<1); + slot1 = (nr_tti_rx<<1) + 1; + pilot0 = 0; + if (ue->frame_parms.Ncp == 0) { // normal prefix + pilot1 = 4; + } else { // extended prefix + pilot1 = 3; + } + + //LOG_I(PHY,"Set available channelEst to 0 AbsSubframe %d.%d \n",frame_rx,nr_tti_rx); + //LOG_I(PHY,"Set available llrs slot1 to 0 AbsSubframe %d.%d \n",frame_rx,nr_tti_rx); + //LOG_I(PHY,"Set available dci info slot0 to 0 AbsSubframe %d.%d \n",frame_rx,nr_tti_rx); + proc->chan_est_pilot0_slot1_available=0; + proc->llr_slot1_available=0; + proc->dci_slot0_available=0; + proc->first_symbol_available=0; + proc->chan_est_slot1_available=0; + //proc->channel_level=0; + + if (pthread_mutex_lock(&proc->mutex_slot1_dl_processing) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE slot1 dl processing\n",ue->Mod_id ); + exit_fun("nothing to add"); + } + + proc->instance_cnt_slot1_dl_processing++; + if (proc->instance_cnt_slot1_dl_processing == 0) + { + LOG_D(PHY,"unblock slot1 dl processing thread blocked on instance_cnt_slot1_dl_processing : %d \n", proc->instance_cnt_slot1_dl_processing ); + if (pthread_cond_signal(&proc->cond_slot1_dl_processing) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE slot1 processing thread\n", ue->Mod_id); + exit_fun("nothing to add"); + } + if (pthread_mutex_unlock(&proc->mutex_slot1_dl_processing) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE slot1 dl processing \n",ue->Mod_id ); + exit_fun("nothing to add"); + } + + } else + { + LOG_E( PHY, "[SCHED][UE %d] UE RX thread busy (IC %d)!!\n", ue->Mod_id, proc->instance_cnt_slot1_dl_processing); + if (proc->instance_cnt_slot1_dl_processing > 2) + exit_fun("instance_cnt_slot1_dl_processing > 2"); + } + //AssertFatal(pthread_cond_signal(&proc->cond_slot1_dl_processing) ==0 ,""); + AssertFatal(pthread_mutex_unlock(&proc->mutex_slot1_dl_processing) ==0,""); + + + /**** Slot0 FE Processing ****/ + // I- start main thread for FFT/ChanEst symbol: 0/1 --> 7 +#if UE_TIMING_TRACE + start_meas(&ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0]); +#endif + // 1- perform FFT for pilot ofdm symbols first (ofdmSym7 ofdmSym4 or (ofdmSym6 ofdmSym3)) + //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot1,pilot0); + front_end_fft(ue, + pilot0, + slot1, + 0, + 0); + //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot0,pilot1); + front_end_fft(ue, + pilot1, + slot0, + 0, + 0); + //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot0,pilot1); + front_end_chanEst(ue, + pilot1, + slot0, + 0); + //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot1,pilot0); + front_end_chanEst(ue, + pilot0, + slot1, + 0); + proc->chan_est_pilot0_slot1_available = 1; + //printf("Set available channelEst to 1 AbsSubframe %d.%d \n",frame_rx,nr_tti_rx); + + // 2- perform FFT for other ofdm symbols other than pilots + for (l=first_ofdm_sym; l<=l2; l++) + { + if( (l != pilot0) && (l != pilot1)) + { + //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot0,l); +#if UE_TIMING_TRACE + start_meas(&ue->ofdm_demod_stats); +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); + front_end_fft(ue, + l, + slot0, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&ue->ofdm_demod_stats); +#endif + } + } // for l=1..l2 + + // 3- perform Channel Estimation for slot0 + for (l=first_ofdm_sym; l<=l2; l++) + { + if( (l != pilot0) && (l != pilot1)) + { + //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot0,l); + front_end_chanEst(ue, + l, + slot0, + 0); + } + ue_measurement_procedures(l-1,ue,proc,eNB_id,(nr_tti_rx<<1),abstraction_flag,mode); + } + + if (do_pdcch_flag) { +#if UE_TIMING_TRACE + start_meas(&ue->pdcch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#endif + if (ue_pdcch_procedures(eNB_id,ue,proc,abstraction_flag) == -1) { + LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,nr_tti_rx); +#if UE_TIMING_TRACE + stop_meas(&ue->pdcch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] Slot0: PDCCH %5.2f \n",frame_rx,nr_tti_rx,ue->pdcch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] Slot0: PDCCH %5.2f \n",frame_rx,nr_tti_rx,ue->pdcch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#endif +#endif + //proc->dci_slot0_available = 1; + return(-1); + } + //proc->dci_slot0_available=1; +#if UE_TIMING_TRACE + stop_meas(&ue->pdcch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] Slot0: PDCCH %5.2f \n",frame_rx,nr_tti_rx,ue->pdcch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] Slot0: PDCCH %5.2f \n",frame_rx,nr_tti_rx,ue->pdcch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#endif +#endif + } + + //printf("num_pdcch_symbols %d\n",ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols); + + // first slot has been processed (FFTs + Channel Estimation, PCFICH/PHICH/PDCCH) +#if UE_TIMING_TRACE + stop_meas(&ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",frame_rx,nr_tti_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",frame_rx,nr_tti_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0].p_time/(cpuf*1000.0)); +#endif +#endif + + //wait until slot1 FE is done + uint32_t wait = 0; + while(proc->chan_est_slot1_available == 0) + { + usleep(1); + wait++; + } + +#if UE_TIMING_TRACE + stop_meas(&ue->ue_front_end_stat[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] FULL FE Processing %5.2f \n",frame_rx,nr_tti_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] FULL FE Processing %5.2f \n",frame_rx,nr_tti_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0].p_time/(cpuf*1000.0)); +#endif +#endif + /**** End nr_tti_rx FE Processing ****/ + + +#if 0 + //Trigger LLR parallelized for Slot 1 + proc->dci_slot0_available=1; + printf("Set available dci slot0 to 1 AbsSubframe %d.%d \n",frame_rx%1024,nr_tti_rx); +#endif + + /**** Pdsch Procedure Slot0 ****/ + // start main thread for Pdsch Procedure (slot0) + // do procedures for C-RNTI + //printf("AbsSubframe %d.%d Pdsch Procedure (slot0)\n",frame_rx%1024,nr_tti_rx); + //printf("AbsSubframe %d.%d Pdsch Procedure PDSCH Active %d \n",frame_rx%1024,nr_tti_rx, ue->dlsch[ue->current_thread_id[nr_tti_rx]][0][0]->active); + +#if UE_TIMING_TRACE + start_meas(&ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#endif + +#if UE_TIMING_TRACE + start_meas(&ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0]); +#endif + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], + NULL, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + (ue->frame_parms.symbols_per_tti>>1)-1, + abstraction_flag); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + (ue->frame_parms.symbols_per_tti>>1)-1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + (ue->frame_parms.symbols_per_tti>>1)-1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT); + } + + // do procedures for RA-RNTI + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + (ue->frame_parms.symbols_per_tti>>1)-1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); + } + +#if 1 + // LLR linear + proc->dci_slot0_available=1; + //printf("Set available dci slot0 to 1 AbsSubframe %d.%d \n",frame_rx%1024,nr_tti_rx); +#endif + +#if UE_TIMING_TRACE + stop_meas(&ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] Slot0: LLR Computation %5.2f \n",frame_rx,nr_tti_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] Slot0: LLR Computation %5.2f \n",frame_rx,nr_tti_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][0].p_time/(cpuf*1000.0)); +#endif +#endif + + + //wait until LLR Slot1 is done + wait = 0; + while(proc->llr_slot1_available == 0) + { + usleep(1); + wait++; + } + + + +#if UE_TIMING_TRACE + stop_meas(&ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] Full LLR Computation %5.2f \n",frame_rx,nr_tti_rx,ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] Full LLR Computation %5.2f \n",frame_rx,nr_tti_rx,ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#endif +#endif + //printf("[slot0 dl processing] AbsSubframe %d.%d Channel Decoder Start wait %d\n",frame_rx,nr_tti_rx,wait); + + + //=====================================================================// +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#endif + + LOG_D(PHY,"==> Start Turbo Decoder active dlsch %d SI %d RA %d \n",ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active, + ue->dlsch_SI[eNB_id]->active, + //ue->dlsch_p[eNB_id]->active, + ue->dlsch_ra[eNB_id]->active); + // Start Turbo decoder + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + ue_dlsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1], + &ue->dlsch_errors[eNB_id], + mode, + abstraction_flag); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + ue_dlsch_procedures(ue, + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + &ue->dlsch_SI_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_SI[eNB_id]->active = 0; + } + + // do procedures for P-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + ue_dlsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + &ue->dlsch_p_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_p[eNB_id]->active = 0; + } + // do procedures for RA-RNTI + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + ue_dlsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + &ue->dlsch_ra_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_ra[eNB_id]->active = 0; + } + +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf("[AbsSFN %d.%d] Channel Decoder: %5.2f \n",frame_rx,nr_tti_rx,ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[AbsSFN %d.%d] Channel Decoder: %5.2f \n",frame_rx,nr_tti_rx,ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#endif + +#endif + + // duplicate harq structure + uint8_t current_harq_pid = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid; + NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[current_harq_pid]; + nr_harq_status_t *current_harq_ack = &ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_ack[nr_tti_rx]; + + // For Debug parallelisation + //if (current_harq_ack->ack == 0) { + //printf("[slot0 dl processing][End of Channel Decoding] AbsSubframe %d.%d Decode Fail for HarqId%d Round%d\n",frame_rx,nr_tti_rx,current_harq_pid,current_harq_processes->round); + //} + for(uint8_t rx_th_idx=1; rx_th_idx<RX_NB_TH; rx_th_idx++) + { + NR_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[ue->current_thread_id[(nr_tti_rx+rx_th_idx)%10]][eNB_id][0]->harq_processes[current_harq_pid]; + nr_harq_status_t *harq_ack_dest = &ue->dlsch[ue->current_thread_id[(nr_tti_rx+rx_th_idx)%10]][eNB_id][0]->harq_ack[nr_tti_rx]; + + copy_harq_proc_struct(harq_processes_dest, current_harq_processes); + copy_ack_struct(harq_ack_dest, current_harq_ack); + + } + /* + NR_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[(nr_tti_rx+1)%RX_NB_TH][eNB_id][0]->harq_processes[current_harq_pid]; + NR_DL_UE_HARQ_t *harq_processes_dest1 = ue->dlsch[(nr_tti_rx+2)%RX_NB_TH][eNB_id][0]->harq_processes[current_harq_pid]; + + nr_harq_status_t *current_harq_ack = &ue->dlsch[nr_tti_rx%RX_NB_TH][eNB_id][0]->harq_ack[nr_tti_rx]; + nr_harq_status_t *harq_ack_dest = &ue->dlsch[(nr_tti_rx+1)%RX_NB_TH][eNB_id][0]->harq_ack[nr_tti_rx]; + nr_harq_status_t *harq_ack_dest1 = &ue->dlsch[(nr_tti_rx+2)%RX_NB_TH][eNB_id][0]->harq_ack[nr_tti_rx]; + + copy_harq_proc_struct(harq_processes_dest, current_harq_processes); + copy_ack_struct(harq_ack_dest, current_harq_ack); + + copy_harq_proc_struct(harq_processes_dest1, current_harq_processes); + copy_ack_struct(harq_ack_dest1, current_harq_ack); + */ + if (nr_tti_rx==9) { + if (frame_rx % 10 == 0) { + if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) + ue->dlsch_fer[eNB_id] = (100*(ue->dlsch_errors[eNB_id] - ue->dlsch_errors_last[eNB_id]))/(ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]); + + ue->dlsch_errors_last[eNB_id] = ue->dlsch_errors[eNB_id]; + ue->dlsch_received_last[eNB_id] = ue->dlsch_received[eNB_id]; + } + + + ue->bitrate[eNB_id] = (ue->total_TBS[eNB_id] - ue->total_TBS_last[eNB_id])*100; + ue->total_TBS_last[eNB_id] = ue->total_TBS[eNB_id]; + LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", + ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], + ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); + +#if UE_AUTOTEST_TRACE + if ((frame_rx % 100 == 0)) { + LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[eNB_id]/1000.0, frame_rx); + } +#endif + + } + +#ifdef EMOS + phy_procedures_emos_UE_RX(ue,slot,eNB_id); +#endif + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); + +#if UE_TIMING_TRACE + stop_meas(&ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf("------FULL RX PROC [AbsSFN %d.%d]: %5.2f ------\n",frame_rx,nr_tti_rx,ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "------FULL RX PROC [AbsSFN %d.%d]: %5.2f ------\n",frame_rx,nr_tti_rx,ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#endif +#endif + + LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); + return (0); +} +#endif + +#endif + + + + +int phy_procedures_UE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id, + uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode, + relaying_type_t r_type) { + + int l,l2; + int pilot1; + int pmch_flag=0; + int frame_rx = proc->frame_rx; + int nr_tti_rx = proc->nr_tti_rx; + proc->decoder_switch = 0; + //int counter_decoder = 0; + + uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); + uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); + +#if T_TRACER + T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_tti_rx)); + + T(T_UE_PHY_INPUT_SIGNAL, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_tti_rx), T_INT(0), + T_BUFFER(&ue->common_vars.rxdata[0][nr_tti_rx*ue->frame_parms.samples_per_subframe], + ue->frame_parms.samples_per_subframe * 4)); +#endif + + // start timers +#ifdef UE_DEBUG_TRACE + LOG_I(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); +#endif + +#if UE_TIMING_TRACE + start_meas(&ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]]); + start_meas(&ue->generic_stat); +#endif + + pmch_flag = is_pmch_subframe(frame_rx,nr_tti_rx,&ue->frame_parms) ? 1 : 0; + + if (do_pdcch_flag) { + // deactivate reception until we scan pdcch + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]) + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 0; + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1]) + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1]->active = 0; + + if (ue->dlsch_SI[eNB_id]) + ue->dlsch_SI[eNB_id]->active = 0; + if (ue->dlsch_p[eNB_id]) + ue->dlsch_p[eNB_id]->active = 0; + if (ue->dlsch_ra[eNB_id]) + ue->dlsch_ra[eNB_id]->active = 0; + } + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[%s %d] Frame %d nr_tti_rx %d: Doing phy_procedures_UE_RX\n", + (r_type == multicast_relay) ? "RN/UE" : "UE", + ue->Mod_id,frame_rx, nr_tti_rx); +#endif + + if (ue->frame_parms.Ncp == 0) { // normal prefix + pilot1 = 4; + } else { // extended prefix + pilot1 = 3; + } + + + if (nr_subframe_select(&ue->frame_parms,nr_tti_rx) == SF_S) { // S-subframe, do first 5 symbols only + l2 = 5; + } else if (pmch_flag == 1) { // do first 2 symbols only + l2 = 1; + } else { // normal nr_tti_rx, last symbol to be processed is the first of the second slot + l2 = (ue->frame_parms.symbols_per_tti/2)-1; + } + + int prev_nr_tti_rx = (nr_tti_rx - 1)<0? 9: (nr_tti_rx - 1); + if (nr_subframe_select(&ue->frame_parms,prev_nr_tti_rx) != SF_DL) { + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // RX processing of symbols l=0...l2 + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + l=0; + } else { + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch) + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + l=1; + } + + LOG_D(PHY," ------ slot 0 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + + + + for (; l<=3; l++) { + if (abstraction_flag == 0) { +#if UE_TIMING_TRACE + start_meas(&ue->ofdm_demod_stats); +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); + slot_fep_pbch(ue, + l, + (nr_tti_rx<<1), + 0, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&ue->ofdm_demod_stats); +#endif + } + + //ue_measurement_procedures(l-1,ue,proc,eNB_id,(nr_tti_rx<<1),abstraction_flag,mode); + + if (do_pdcch_flag) { +// if ((l==pilot1) || ((pmch_flag==1)&(l==l2))) { +// LOG_D(PHY,"[UE %d] Frame %d: Calling pdcch procedures (eNB %d)\n",ue->Mod_id,frame_rx,eNB_id); + + //start_meas(&ue->rx_pdcch_stats[ue->current_thread_id[nr_tti_rx]]); + if (nr_ue_pdcch_procedures(eNB_id,ue,proc,abstraction_flag) == -1) { + LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,nr_tti_rx); + return(-1); + } + //stop_meas(&ue->rx_pdcch_stats[ue->current_thread_id[nr_tti_rx]]); + //printf("nr_tti_rx %d n_pdcch_sym %d pdcch procedures %5.3f \n", + // nr_tti_rx, ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + // (ue->rx_pdcch_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); + LOG_D(PHY,"num_pdcch_symbols %d\n",ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols); +// } + } + + } // for l=1..l2 + +#if 0 + ue_measurement_procedures(l-1,ue,proc,eNB_id,(nr_tti_rx<<1),abstraction_flag,mode); + + LOG_D(PHY," ------ end FFT/ChannelEst/PDCCH slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + // If this is PMCH, call procedures and return + if (pmch_flag == 1) { + ue_pmch_procedures(ue,proc,eNB_id,abstraction_flag); + return 0; + } + + slot_fep_pbch(ue, + 0, + 1+(nr_tti_rx<<1), + 0, + 0, + 0); + + // first slot has been processed (FFTs + Channel Estimation, PCFICH/PHICH/PDCCH) +#if UE_TIMING_TRACE + stop_meas(&ue->generic_stat); +#if DISABLE_LOG_X + printf("[SFN %d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",nr_tti_rx,ue->generic_stat.p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[SFN %d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",nr_tti_rx,ue->generic_stat.p_time/(cpuf*1000.0)); +#endif + +#endif + + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); +#if UE_TIMING_TRACE + start_meas(&ue->generic_stat); +#endif + // do procedures for C-RNTI + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], + NULL, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); + } + + LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + // do procedures for SI-RNTI + if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT); + } + + // do procedures for RA-RNTI + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); + } + + LOG_D(PHY," ------ slot 1 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + + if (nr_subframe_select(&ue->frame_parms,nr_tti_rx) != SF_S) { // do front-end processing for second slot, and first symbol of next nr_tti_rx + for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) { + if (abstraction_flag == 0) { +#if UE_TIMING_TRACE + start_meas(&ue->ofdm_demod_stats); +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); + slot_fep(ue, + l, + 1+(nr_tti_rx<<1), + 0, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(&ue->ofdm_demod_stats); +#endif + } + + ue_measurement_procedures(l-1,ue,proc,eNB_id,1+(nr_tti_rx<<1),abstraction_flag,mode); + + } // for l=1..l2 + + // do first symbol of next downlink nr_tti_rx for channel estimation + int next_nr_tti_rx = (1+nr_tti_rx)%10; + if (nr_subframe_select(&ue->frame_parms,next_nr_tti_rx) != SF_UL) + { + slot_fep(ue, + 0, + (next_nr_tti_rx<<1), + 0, + 0, + 0); + } + } // not an S-subframe +#if UE_TIMING_TRACE + stop_meas(&ue->generic_stat); +#if DISABLE_LOG_X + printf("[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",nr_tti_rx,ue->generic_stat.p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",nr_tti_rx,ue->generic_stat.p_time/(cpuf*1000.0)); +#endif + +#endif + + LOG_D(PHY," ------ end FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + + if ( (nr_tti_rx == 0) && (ue->decode_MIB == 1)) + { + ue_pbch_procedures(eNB_id,ue,proc,abstraction_flag); + } + + + + // do procedures for C-RNTI + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { + /*proc->counter_decoder++; + printf("counter decoder %d\n", proc->counter_decoder); + if (proc->counter_decoder > 6) + { + proc->decoder_switch = 1; + printf("switch to LDPC\n"); + }*/ + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); +#if UE_TIMING_TRACE + start_meas(&ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#endif + ue_pdsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + LOG_D(PHY," ------ --> PDSCH Turbo Decoder slot 0/1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); +#if UE_TIMING_TRACE + stop_meas(&ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); + start_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#endif + ue_dlsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1], + &ue->dlsch_errors[eNB_id], + mode, + abstraction_flag); +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf("[SFN %d] Slot1: Pdsch Proc %5.2f\n",nr_tti_rx,ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); + printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_tti_rx,ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n",nr_tti_rx,ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); + LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_tti_rx,ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#endif + +#endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); + + } +#if UE_TIMING_TRACE + start_meas(&ue->generic_stat); +#endif + +#if 0 + if(nr_tti_rx==5 && ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid]->nb_rb > 20){ + //write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); + //write_output("llr.m","llr", &ue->pdsch_vars[eNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); + + write_output("rxdataF0_current.m" , "rxdataF0", &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0][0],14*ue->frame_parms.ofdm_symbol_size,1,1); + //write_output("rxdataF0_previous.m" , "rxdataF0_prev_sss", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*ue->frame_parms.ofdm_symbol_size,1,1); + + //write_output("rxdataF0_previous.m" , "rxdataF0_prev", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*ue->frame_parms.ofdm_symbol_size,1,1); + + write_output("dl_ch_estimates.m", "dl_ch_estimates_sfn5", &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[0][0][0],14*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_estimates_ext[0][0],14*ue->frame_parms.N_RB_DL*12,1,1); + write_output("rxdataF_comp00.m","rxdataF_comp00", &ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->rxdataF_comp0[0][0],14*ue->frame_parms.N_RB_DL*12,1,1); + //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_mag0[0][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_magb0[0][0],14*frame_parms->N_RB_DL*12,1,1); + + AssertFatal (0,""); + } +#endif + + // do procedures for SI-RNTI + if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + + ue_dlsch_procedures(ue, + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + &ue->dlsch_SI_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_SI[eNB_id]->active = 0; + } + + // do procedures for P-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + + ue_dlsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + &ue->dlsch_p_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_p[eNB_id]->active = 0; + } + // do procedures for RA-RNTI + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + ue_dlsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + &ue->dlsch_ra_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_ra[eNB_id]->active = 0; + } + + // duplicate harq structure + + uint8_t current_harq_pid = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid; + NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[current_harq_pid]; + NR_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[next1_thread_id][eNB_id][0]->harq_processes[current_harq_pid]; + NR_DL_UE_HARQ_t *harq_processes_dest1 = ue->dlsch[next2_thread_id][eNB_id][0]->harq_processes[current_harq_pid]; + + nr_harq_status_t *current_harq_ack = &ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_ack[nr_tti_rx]; + nr_harq_status_t *harq_ack_dest = &ue->dlsch[next1_thread_id][eNB_id][0]->harq_ack[nr_tti_rx]; + nr_harq_status_t *harq_ack_dest1 = &ue->dlsch[next2_thread_id][eNB_id][0]->harq_ack[nr_tti_rx]; + + copy_harq_proc_struct(harq_processes_dest, current_harq_processes); + copy_ack_struct(harq_ack_dest, current_harq_ack); + + copy_harq_proc_struct(harq_processes_dest1, current_harq_processes); + copy_ack_struct(harq_ack_dest1, current_harq_ack); + + if (nr_tti_rx==9) { + if (frame_rx % 10 == 0) { + if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) + ue->dlsch_fer[eNB_id] = (100*(ue->dlsch_errors[eNB_id] - ue->dlsch_errors_last[eNB_id]))/(ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]); + + ue->dlsch_errors_last[eNB_id] = ue->dlsch_errors[eNB_id]; + ue->dlsch_received_last[eNB_id] = ue->dlsch_received[eNB_id]; + } + + + ue->bitrate[eNB_id] = (ue->total_TBS[eNB_id] - ue->total_TBS_last[eNB_id])*100; + ue->total_TBS_last[eNB_id] = ue->total_TBS[eNB_id]; + LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", + ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], + ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); + + #if UE_AUTOTEST_TRACE + if ((frame_rx % 100 == 0)) { + LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[eNB_id]/1000.0, frame_rx); + } + #endif + + } + +#if UE_TIMING_TRACE + stop_meas(&ue->generic_stat); + printf("after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0)); +#endif + +#ifdef EMOS + phy_procedures_emos_UE_RX(ue,slot,eNB_id); +#endif + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); + +#if UE_TIMING_TRACE + stop_meas(&ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]]); +#if DISABLE_LOG_X + printf("------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_tti_rx,ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#else + LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_tti_rx,ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); +#endif +#endif +#endif + + LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); + return (0); +} + + +#if 0 +#if defined(Rel10) || defined(Rel14) + +int phy_procedures_RN_UE_RX(uint8_t slot_rx, uint8_t next_slot, relaying_type_t r_type) +{ + + int do_proc =0; // do nothing by default + + switch(r_type) { + case no_relay: + do_proc=no_relay; // perform the normal UE operation + break; + + case multicast_relay: + if (slot_rx > 12) + do_proc = 0; // do nothing + else // SF#1, SF#2, SF3, SF#3, SF#4, SF#5, SF#6(do rx slot 12) + do_proc = multicast_relay ; // do PHY procedures UE RX + + break; + + default: // should'not be here + LOG_W(PHY,"Not supported relay type %d, do nothing \n", r_type); + do_proc= 0; + break; + } + + return do_proc; +} +#endif + +void phy_procedures_UE_lte(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode, + relaying_type_t r_type) +{ +#if defined(ENABLE_ITTI) + MessageDef *msg_p; + const char *msg_name; + instance_t instance; + unsigned int Mod_id; + int result; +#endif + + int frame_rx = proc->frame_rx; + int frame_tx = proc->frame_tx; + int nr_tti_rx = proc->nr_tti_rx; + int nr_tti_tx = proc->nr_tti_tx; +//#ifdef UE_NR_PHY_DEMO +// int nr_tti_rx = proc->nr_tti_rx; +// int nr_tti_tx = proc->nr_tti_tx; +//#endif + +#undef DEBUG_PHY_PROC + + UE_L2_STATE_t ret; + int slot; + + if (ue->mac_enabled == 0) { + ue->UE_mode[eNB_id]=PUSCH; + } + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_LTE,1); +#if UE_TIMING_TRACE + start_meas(&ue->phy_proc[ue->current_thread_id[nr_tti_rx]]); +#endif +#if defined(ENABLE_ITTI) + + do { + // Checks if a message has been sent to PHY sub-task + itti_poll_msg (TASK_PHY_UE, &msg_p); + + if (msg_p != NULL) { + msg_name = ITTI_MSG_NAME (msg_p); + instance = ITTI_MSG_INSTANCE (msg_p); + Mod_id = instance - NB_eNB_INST; + + switch (ITTI_MSG_ID(msg_p)) { + case PHY_FIND_CELL_REQ: + LOG_I(PHY, "[UE %d] Received %s\n", Mod_id, msg_name); + + /* TODO process the message */ + break; + + default: + LOG_E(PHY, "[UE %d] Received unexpected message %s\n", Mod_id, msg_name); + break; + } + + result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + } + } while(msg_p != NULL); + +#endif + + for (slot=0;slot<2;slot++) { + + if ((nr_subframe_select(&ue->frame_parms,nr_tti_tx)==SF_UL)|| + (ue->frame_parms.frame_type == FDD)) { + phy_procedures_UE_TX(ue,proc,eNB_id,abstraction_flag,mode,r_type); + } + + if ((nr_subframe_select(&ue->frame_parms,nr_tti_rx)==SF_DL) || + (ue->frame_parms.frame_type == FDD)) { +#if defined(Rel10) || defined(Rel14) + + if (phy_procedures_RN_UE_RX(nr_tti_rx, nr_tti_tx, r_type) != 0 ) +#endif + phy_procedures_UE_RX(ue,proc,eNB_id,abstraction_flag,do_pdcch_flag,mode,r_type); + } + + if ((nr_subframe_select(&ue->frame_parms,nr_tti_tx)==SF_S) && + (slot==1)) { + phy_procedures_UE_S_TX(ue,eNB_id,abstraction_flag,r_type); + } + + if ((nr_subframe_select(&ue->frame_parms,nr_tti_rx)==SF_S) && + (slot==0)) { +#if defined(Rel10) || defined(Rel14) + + if (phy_procedures_RN_UE_RX(nr_tti_rx, nr_tti_tx, r_type) != 0 ) +#endif + phy_procedures_UE_RX(ue,proc,eNB_id,abstraction_flag,do_pdcch_flag,mode,r_type); + } + + if (ue->mac_enabled==1) { + if (slot==0) { +//#ifdef UE_NR_PHY_DEMO + ret = mac_xface->ue_scheduler(ue->Mod_id, + frame_rx, + proc->subframe_rx, + nr_tti_rx%(ue->frame_parms.ttis_per_subframe), + frame_tx, + proc->subframe_tx, + nr_tti_tx%(ue->frame_parms.ttis_per_subframe), + nr_subframe_select(&ue->frame_parms,nr_tti_tx), + eNB_id, + 0/*FIXME CC_id*/); +//#else +/* ret = mac_xface->ue_scheduler(ue->Mod_id, + frame_rx, + nr_tti_rx, + frame_tx, + nr_tti_tx, + nr_subframe_select(&ue->frame_parms,nr_tti_tx), + eNB_id,*/ +// 0/*FIXME CC_id*/); +//#endif + + if (ret == CONNECTION_LOST) { + LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d RRC Connection lost, returning to PRACH\n",ue->Mod_id, + frame_rx,nr_tti_tx); + ue->UE_mode[eNB_id] = PRACH; + // mac_xface->macphy_exit("Connection lost"); + } else if (ret == PHY_RESYNCH) { + LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d RRC Connection lost, trying to resynch\n", + ue->Mod_id, + frame_rx,nr_tti_tx); + ue->UE_mode[eNB_id] = RESYNCH; + // mac_xface->macphy_exit("Connection lost"); + } else if (ret == PHY_HO_PRACH) { + LOG_I(PHY,"[UE %d] Frame %d, nr_tti_rx %d, return to PRACH and perform a contention-free access\n", + ue->Mod_id,frame_rx,nr_tti_tx); + ue->UE_mode[eNB_id] = PRACH; + } + } + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_LTE,0); +#if UE_TIMING_TRACE + stop_meas(&ue->phy_proc[ue->current_thread_id[nr_tti_rx]]); +#endif + } // slot +} +#endif + diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index c699ad5232b8761475644a3a677965e1e78913b3..a08be4dead582ea258cb4e7f8c9341ad18f4b71b 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -29,98 +29,101 @@ * @ingroup _mac */ +#include "defs.h" +#include "proto.h" int nr_rrc_mac_config_req_ue( - module_id_t Mod_idP, - int CC_idP, - uint8_t eNB_index, - MAC_CellGroupConfig_t *mac_cell_group_config, - PhysicalCellGroupConfig_t *phy_cell_group_config, - SpCellConfig_t *spcell_config){ + module_id_t module_id, + int CC_idP, + uint8_t gNB_index, + NR_MIB_t *mibP, + NR_MAC_CellGroupConfig_t *mac_cell_group_configP, + NR_PhysicalCellGroupConfig_t *phy_cell_group_configP, + NR_SpCellConfig_t *spcell_configP ){ - NR_UE_MAC_INST *mac = get_mac_inst(Mod_idP); + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - ServingCellConfig_t *serving_cell_config = spcell_config->spCellConfigDedicated; +// NR_ServingCellConfig_t *serving_cell_config = spcell_configP->spCellConfigDedicated; // TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc. - if(mac_cell_group_config != (MAC_CellGroupConfig_t *)0){ - if(mac_cell_group_config->drx_Config != (drx_Config_t *)0 ){ - mac->drx_Config = mac_cell_group_config->drx_Config; + if(mibP != NULL){ + ; + } + + if(mac_cell_group_configP != NULL){ + if(mac_cell_group_configP->drx_Config != NULL ){ + mac->drx_Config = mac_cell_group_configP->drx_Config; } - if(mac_cell_group_config->SchedulingRequestConfig != (SchedulingRequestConfig_t *)0 ){ - mac->SchedulingRequestConfig = mac_cell_group_config->SchedulingRequestConfig; + if(mac_cell_group_configP->schedulingRequestConfig != NULL ){ + mac->schedulingRequestConfig = mac_cell_group_configP->schedulingRequestConfig; } - if(mac_cell_group_config->BSR_Config != (BSR_Config_t *)0 ){ - mac->BSR_Config = mac_cell_group_config->BSR_Config; + if(mac_cell_group_configP->bsr_Config != NULL ){ + mac->bsr_Config = mac_cell_group_configP->bsr_Config; } - if(mac_cell_group_config->TAG_Config != (TAG_Config_t *)0 ){ - mac->TAG_Config = mac_cell_group_config->TAG_Config; + if(mac_cell_group_configP->tag_Config != NULL ){ + mac->tag_Config = mac_cell_group_configP->tag_Config; } - if(mac_cell_group_config->phr_Config != (phr_Config_t *)0 ){ - mac->phr_Config = mac_cell_group_config->phr_Config; + if(mac_cell_group_configP->phr_Config != NULL ){ + mac->phr_Config = mac_cell_group_configP->phr_Config; } - if(mac_cell_group_config->cs_RNTI != (cs_RNTI_t *)0 ){ - mac->cs_RNTI = mac_cell_group_config->cs_RNTI; + if(mac_cell_group_configP->cs_RNTI != NULL ){ + mac->cs_RNTI = mac_cell_group_configP->cs_RNTI; } } - if(phy_cell_group_config != (PhysicalCellGroupConfig_t *)0){ - config_phy(phy_cell_group_config, NULL); + if(phy_cell_group_configP != NULL ){ + //config_phy(phy_cell_group_config, NULL); } - if(serving_cell_config_config != (SpCellConfig_t *)0){ - config_phy(NULL, spcell_config); +// TODO check +#if 0 + if(serving_cell_config_configP != NULL ){ + //config_phy(NULL, spcell_config); mac->servCellIndex = spcell_config->servCellIndex; } - if(serving_cell_config != (spCellConfigDedicated_t *)0){ - if(serving_cell_config->tdd_UL_DL_ConfigurationDedicated != (TDD_UL_DL_ConfigDedicated_t *)0){ + if(serving_cell_config != NULL ){ + if(serving_cell_config->tdd_UL_DL_ConfigurationDedicated != NULL ){ mac->tdd_UL_DL_ConfigurationDedicated = serving_cell_config->tdd_UL_DL_ConfigurationDedicated; } - if(spcell_config->initialDownlinkBWP != (BWP_DownlinkDedicated_t *)0){ + if(spcell_config->initialDownlinkBWP != NULL ){ mac->init_DL_BWP = spcell_config->initialDownlinkBWP; } // storage list of DL BWP config. TODO should be modify to maintain(add/release) a list inside MAC instance, this implementation just use for one-shot RRC configuration setting. - if(spcell_config->downlinkBWP_ToAddModList != (struct ServingCellConfig__downlinkBWP_ToAddModList *)0){ + if(spcell_config->downlinkBWP_ToAddModList != NULL ){ mac->BWP_Downlink_list = spcell_config->downlinkBWP_ToAddModList->list; mac->BWP_Downlink_count = spcell_config->downlinkBWP_ToAddModList->count; } - if(spcell_config->bwp_InactivityTimer != (long *)0){ + if(spcell_config->bwp_InactivityTimer != NULL ){ mac->bwp_InactivityTimer = spcell_config->bwp_InactivityTimer; } - if(spcell_config->defaultDownlinkBWP_Id != (BWP_Id_t *)0){ + if(spcell_config->defaultDownlinkBWP_Id != NULL ){ mac->defaultDownlinkBWP_Id = spcell_config->defaultDownlinkBWP_Id; } - if(spcell_config->pdsch_ServingCellConfig != (PDSCH_ServingCellConfig_t *)0){ + if(spcell_config->pdsch_ServingCellConfig != NULL ){ mac->pdsch_ServingCellConfig = spcell_config->pdsch_ServingCellConfig; } - if(spcell_config->csi_MeasConfig != (CSI_MeasConfig_t *)0){ + if(spcell_config->csi_MeasConfig != NULL ){ mac->csi_MeasConfig = spcell_config->csi_MeasConfig; } spcell_config->tag_Id = spcell_config.tag_Id; } - +#endif //scell config not yet - - - - - - - return (0); -} + return 0; +} \ No newline at end of file diff --git a/openair2/LAYER2/NR_MAC_UE/defs.h b/openair2/LAYER2/NR_MAC_UE/defs.h index e7329616b7fca0654f0c98e2f051c6b76786131f..61f83074d3ec202fb72c749eceff95f66df278b6 100644 --- a/openair2/LAYER2/NR_MAC_UE/defs.h +++ b/openair2/LAYER2/NR_MAC_UE/defs.h @@ -34,8 +34,8 @@ /*@}*/ -#ifndef __LAYER2_MAC_DEFS_H__ -#define __LAYER2_MAC_DEFS_H__ +#ifndef __LAYER2_NR_MAC_DEFS_H__ +#define __LAYER2_NR_MAC_DEFS_H__ @@ -43,66 +43,37 @@ #include <stdlib.h> #include <string.h> -#include "PHY/defs.h" -#include "PHY/LTE_TRANSPORT/defs.h" -#include "COMMON/platform_constants.h" -#include "BCCH-BCH-Message.h" -#include "RadioResourceConfigCommon.h" -#include "RadioResourceConfigDedicated.h" -#include "MeasGapConfig.h" -#include "SchedulingInfoList.h" -#include "TDD-Config.h" -#include "RACH-ConfigCommon.h" -#include "MeasObjectToAddModList.h" -#include "MobilityControlInfo.h" -#if defined(Rel10) || defined(Rel14) -#include "MBSFN-AreaInfoList-r9.h" -#include "MBSFN-SubframeConfigList.h" -#include "PMCH-InfoList-r9.h" -#include "SCellToAddMod-r10.h" -#endif -#ifdef Rel14 -#include "SystemInformationBlockType1-v1310-IEs.h" -#endif +#include "platform_types.h" -#include "nfapi_interface.h" -#include "PHY_INTERFACE/IF_Module.h" +#include "NR_DRX-Config.h" +#include "NR_SchedulingRequestConfig.h" +#include "NR_BSR-Config.h" +#include "NR_TAG-Config.h" +#include "NR_PHR-Config.h" +#include "NR_RNTI-Value.h" +#include "NR_MIB.h" +#include "NR_MAC-CellGroupConfig.h" +#include "NR_PhysicalCellGroupConfig.h" +#include "NR_SpCellConfig.h" + +#include "NR_ServingCellConfig.h" + +#define NB_NR_UE_MAC_INST 1 /*!\brief Top level UE MAC structure */ typedef struct { //// MAC config - drx_Config_t *drx_config; - SchedulingRequestConfig_t *SchedulingRequestConfig; - BSR_Config_t *BSR_Config; - TAG_Config_t *TAG_Config; - phr_Config_t *phr_Config; - cs_RNTI_t *cs_RNTI; - ServCellIndex_t *servCellIndex; + NR_DRX_Config_t *drx_Config; /* OPTIONAL */ + NR_SchedulingRequestConfig_t *schedulingRequestConfig; /* OPTIONAL */ + NR_BSR_Config_t *bsr_Config; /* OPTIONAL */ + NR_TAG_Config_t *tag_Config; /* OPTIONAL */ + NR_PHR_Config_t *phr_Config; /* OPTIONAL */ + + NR_RNTI_Value_t *cs_RNTI; /* OPTIONAL */ - //// Serving cell config - TDD_UL_DL_ConfigDedicated_t *tdd_UL_DL_ConfigurationDedicated; - // init DL BWP - BWP_DownlinkDedicated_t *init_DL_BWP; - // DL BWP list, not default one - BWP_Downlink_t **BWP_Downlink_list; - int BWP_Downlink_count; - //BWP_Id_t *firstActiveDownlinkBWP_Id; - long *bwp_InactivityTimer; - BWP_Id_t *defaultDownlinkBWP_Id; - //struct UplinkConfig *uplinkConfig; - //struct UplinkConfig *supplementaryUplink; - PDSCH_ServingCellConfig_t *pdsch_ServingCellConfig; - CSI_MeasConfig_t *csi_MeasConfig; - //SRS_CarrierSwitching_t *carrierSwitching; - //long *sCellDeactivationTimer /* OPTIONAL */; - //struct CrossCarrierSchedulingConfig *crossCarrierSchedulingConfig /* OPTIONAL */; - TAG_Id_t tag_Id; - //long *ue_BeamLockFunction /* OPTIONAL */; - //long *pathlossReferenceLinking /* OPTIONAL */; +} NR_UE_MAC_INST_t; -} UE_MAC_INST; -#include "proto.h" /*@}*/ #endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/extern.h b/openair2/LAYER2/NR_MAC_UE/extern.h new file mode 100644 index 0000000000000000000000000000000000000000..abe787b2b0e864dfa4548f9617f63cd2123a67cf --- /dev/null +++ b/openair2/LAYER2/NR_MAC_UE/extern.h @@ -0,0 +1,125 @@ +/* + * 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 + */ + +/*! \file extern.h +* \brief mac externs +* \author Navid Nikaein and Raymond Knopp +* \date 2010 - 2014 +* \version 1.0 +* \email navid.nikaein@eurecom.fr +* @ingroup _mac + +*/ + +#ifndef __MAC_EXTERN_H__ +#define __MAC_EXTERN_H__ + + +#ifdef USER_MODE +//#include "stdio.h" +#endif //USER_MODE +//#include "PHY/defs.h" +#include "PHY/defs_nr_UE.h" +#include "defs.h" +#include "COMMON/mac_rrc_primitives.h" +#ifdef PHY_EMUL +//#include "SIMULATION/simulation_defs.h" +#endif //PHY_EMUL +//#include "PHY_INTERFACE/defs.h" +//#include "RRC/LITE/defs.h" + +extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE]; +//extern uint32_t EBSR_Level[63]; +extern const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE]; +//extern uint32_t Extended_BSR_TABLE[63]; ----currently not used + +extern const uint8_t cqi2fmt0_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]; + +extern const uint8_t cqi2fmt1x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]; + +extern const uint8_t cqi2fmt2x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]; + +extern UE_MAC_INST *UE_mac_inst; +extern eNB_MAC_INST *eNB_mac_inst; +extern eNB_RRC_INST *eNB_rrc_inst; +extern UE_RRC_INST *UE_rrc_inst; +extern UE_MAC_INST *ue_mac_inst; +extern MAC_RLC_XFACE *Mac_rlc_xface; +extern uint8_t Is_rrc_registered; + +extern eNB_ULSCH_INFO eNB_ulsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 +extern eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 + + + +//#ifndef USER_MODE +//extern MAC_xface *mac_xface; +extern RRC_XFACE *Rrc_xface; + +extern uint8_t Is_rrc_registered; + +#ifndef PHY_EMUL +#ifndef PHYSIM +#define NB_INST 1 +#else +extern unsigned char NB_INST; +#endif +extern unsigned char NB_eNB_INST; +extern unsigned char NB_UE_INST; +extern unsigned char NB_RN_INST; +extern unsigned short NODE_ID[1]; +extern void* bigphys_malloc(int); +#else +extern EMULATION_VARS *Emul_vars; +#endif //PHY_EMUL + + +extern int cqi_to_mcs[16]; + +extern uint32_t RRC_CONNECTION_FLAG; + +extern uint8_t rb_table[33]; + +extern DCI0_5MHz_TDD_1_6_t UL_alloc_pdu; + +extern DCI1A_5MHz_TDD_1_6_t RA_alloc_pdu; +extern DCI1A_5MHz_TDD_1_6_t DLSCH_alloc_pdu1A; +extern DCI1A_5MHz_TDD_1_6_t BCCH_alloc_pdu; + +extern DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu; +extern DCI1_5MHz_TDD_t DLSCH_alloc_pdu; + +extern DCI0_5MHz_FDD_t UL_alloc_pdu_fdd; + +extern DCI1A_5MHz_FDD_t DLSCH_alloc_pdu1A_fdd; +extern DCI1A_5MHz_FDD_t RA_alloc_pdu_fdd; +extern DCI1A_5MHz_FDD_t BCCH_alloc_pdu_fdd; + +extern DCI1A_5MHz_FDD_t CCCH_alloc_pdu_fdd; +extern DCI1_5MHz_FDD_t DLSCH_alloc_pdu_fdd; + +extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu1; +extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2; +extern DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E; + +#endif //DEF_H + + diff --git a/openair2/LAYER2/NR_MAC_UE/mac.h b/openair2/LAYER2/NR_MAC_UE/mac.h new file mode 100644 index 0000000000000000000000000000000000000000..253c855da82136e9c121055fcc29c3043d666a11 --- /dev/null +++ b/openair2/LAYER2/NR_MAC_UE/mac.h @@ -0,0 +1,92 @@ +/* + * 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 + */ + +/*! \file LAYER2/MAC/defs.h +* \brief MAC data structures, constant, and function prototype +* \author Navid Nikaein and Raymond Knopp +* \date 2011 +* \version 0.5 +* \email navid.nikaein@eurecom.fr + +*/ +/** @defgroup _oai2 openair2 Reference Implementation + * @ingroup _ref_implementation_ + * @{ + */ + +/*@}*/ + +#ifndef __LAYER2_MAC_DEFS_H__ +#define __LAYER2_MAC_DEFS_H__ + + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "COMMON/platform_constants.h" +#include "BCCH-BCH-Message.h" +#include "RadioResourceConfigCommon.h" +#include "RadioResourceConfigCommonSIB.h" +#include "RadioResourceConfigDedicated.h" +#include "MeasGapConfig.h" +#include "SchedulingInfoList.h" +#include "TDD-Config.h" +#include "RACH-ConfigCommon.h" +#include "MeasObjectToAddModList.h" +#include "MobilityControlInfo.h" +#if defined(Rel10) || defined(Rel14) +#include "MBSFN-AreaInfoList-r9.h" +#include "MBSFN-SubframeConfigList.h" +#include "PMCH-InfoList-r9.h" +#include "SCellToAddMod-r10.h" +#endif +#ifdef Rel14 +#include "SystemInformationBlockType1-v1310-IEs.h" +#endif + +#include "nfapi_interface.h" +#include "PHY_INTERFACE/IF_Module.h" + +#include "PHY/TOOLS/time_meas.h" + +#include "PHY/defs_common.h" // for PRACH_RESOURCES_t + +#include "targets/ARCH/COMMON/common_lib.h" + +//solve implicit declaration +#include "PHY/LTE_ESTIMATION/lte_estimation.h" +#include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "PHY/LTE_TRANSPORT/transport_common_proto.h" + +/** @defgroup _mac MAC + * @ingroup _oai2 + * @{ + */ + +/*!\brief Values of BCCH logical channel (fake)*/ +#define NR_BCCH_DL_SCH 3 // SI + +/*!\brief Values of PCCH logical channel (fake) */ +#define NR_BCCH_BCH 5 // MIB +/*@}*/ +#endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/vars.c b/openair2/LAYER2/NR_MAC_UE/mac_vars.c similarity index 94% rename from openair2/LAYER2/NR_MAC_UE/vars.c rename to openair2/LAYER2/NR_MAC_UE/mac_vars.c index 300917b3c1f06619f4670fa4f54056e86ae7b275..4ce77e2b93a9755e00e7ba5c21c1e00f86f9fe64 100644 --- a/openair2/LAYER2/NR_MAC_UE/vars.c +++ b/openair2/LAYER2/NR_MAC_UE/mac_vars.c @@ -29,6 +29,8 @@ */ -UE_MAC_INST_t UE_mac_inst; //[NB_MODULE_MAX]; +#include "defs.h" + +NR_UE_MAC_INST_t UE_mac_inst; //[NB_MODULE_MAX]; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index a1c3688fc485f293702905317a016cca180a09d9..8a4bdecd7a4b10089f104612d2a210c7255d78b2 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -31,17 +31,15 @@ #include "defs.h" #include "proto.h" -#include "extern.h" -#include "assertions.h" static NR_UE_MAC_INST_t *nr_ue_mac_inst; int nr_l2_init_ue(void) { - LOG_I(MAC, "[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n"); + //LOG_I(MAC, "[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n"); - LOG_I(MAC, "[MAIN] init UE MAC functions \n"); + //LOG_I(MAC, "[MAIN] init UE MAC functions \n"); //init mac here nr_ue_mac_inst = (NR_UE_MAC_INST_t *)malloc(sizeof(NR_UE_MAC_INST_t)*NB_NR_UE_MAC_INST); @@ -50,6 +48,6 @@ nr_l2_init_ue(void) return (1); } -NR_UE_MAC_INST_t *get_mac_inst(Module_id_t Mod_idP){ +NR_UE_MAC_INST_t *get_mac_inst(module_id_t Mod_idP){ return &nr_ue_mac_inst[(int)Mod_idP]; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c new file mode 100644 index 0000000000000000000000000000000000000000..23b586e914fb89b1fb673ce0c5ff25fea3b7fb2c --- /dev/null +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -0,0 +1,49 @@ +/* + * 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 + */ + +/*! \file ue_procedures.c + * \brief procedures related to UE + * \author Navid Nikaein and Raymond Knopp + * \date 2010 - 2014 + * \version 1 + * \email: navid.nikaein@eurecom.fr + * @ingroup _mac + + */ +#include "proto.h" +#include "RRC/NR_UE/rrc_proto.h" + +void +nr_ue_decode_mib( + module_id_t module_id, + int CC_id, + uint8_t gNB_index, + uint8_t extra_bits, + uint32_t ssb_index, + uint32_t *frameP, + void *pduP, + uint16_t pdu_len){ + + nr_mac_rrc_data_ind_ue( module_id, CC_id, gNB_index, frameP, + NR_BCCH_BCH, (uint8_t *) pduP, pdu_len ); + + // frame calculation +} diff --git a/openair2/LAYER2/NR_MAC_UE/proto.h b/openair2/LAYER2/NR_MAC_UE/proto.h new file mode 100644 index 0000000000000000000000000000000000000000..1545ca9e7ddc28b922cfe050d17384cd4a61bd74 --- /dev/null +++ b/openair2/LAYER2/NR_MAC_UE/proto.h @@ -0,0 +1,61 @@ +/* + * 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 + */ + +/*! \file LAYER2/MAC/proto.h + * \brief MAC functions prototypes for eNB and UE + * \author Navid Nikaein and Raymond Knopp + * \date 2010 - 2014 + * \email navid.nikaein@eurecom.fr + * \version 1.0 + */ +#ifndef __LAYER2_MAC_PROTO_H__ +#define __LAYER2_MAC_PROTO_H__ + +#include "defs.h" + +/**\brief decode mib pdu in NR_UE, from if_module ul_ind with P7 tx_ind message + \param module_id module id + \param CC_id component carrier id + \param gNB_index gNB index + \param extra_bits extra bits for frame calculation + \param ssb_index SSB index for frame calculation + \param frameP pointer to frame for revising after frame calculation + \param pduP pointer to pdu + \param pdu_length length of pdu*/ +void nr_ue_decode_mib(module_id_t module_id, int CC_id, uint8_t gNB_index, uint8_t extra_bits, uint32_t ssb_index, uint32_t *frameP, void *pduP, uint16_t pdu_len); + + +/**\brief primitive from RRC layer to MAC layer for configuration L1/L2, now supported 4 rrc messages: MIB, cell_group_config for MAC/PHY, spcell_config(serving cell config) + \param module_id module id + \param CC_id component carrier id + \param gNB_index gNB index + \param mibP pointer to RRC message MIB + \param mac_cell_group_configP pointer to RRC message MAC-related in cell group config + \param phy_cell_group_configP pointer to RRC message PHY-related in cell group config + \param spcell_configP pointer to RRC message serving cell config*/ +int nr_rrc_mac_config_req_ue( module_id_t module_id, int CC_id, uint8_t gNB_index, NR_MIB_t *mibP, NR_MAC_CellGroupConfig_t *mac_cell_group_configP, NR_PhysicalCellGroupConfig_t *phy_cell_group_configP, NR_SpCellConfig_t *spcell_configP ); + +int nr_l2_init_ue(void); + +NR_UE_MAC_INST_t *get_mac_inst(module_id_t Mod_idP); + +#endif +/** @}*/ diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c new file mode 100644 index 0000000000000000000000000000000000000000..2c51fe4c6cd88c1eb19523195e38dc25c75d9f9c --- /dev/null +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -0,0 +1,57 @@ +/* + * 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 + */ + +/*! \file l2_interface.c + * \brief layer 2 interface, used to support different RRC sublayer + * \author Raymond Knopp and Navid Nikaein + * \date 2010-2014 + * \version 1.0 + * \company Eurecom + * \email: raymond.knopp@eurecom.fr + */ + +#include "rrc_defs.h" +#include "rrc_proto.h" + +typedef uint32_t channel_t; + +int8_t +nr_mac_rrc_data_ind_ue( + const module_id_t module_id, + const int CC_id, + const uint8_t gNB_index, + const uint32_t* frameP, + const channel_t channel, + const uint8_t* pduP, + const sdu_size_t pdu_len){ + + switch(channel){ + case NR_BCCH_BCH: + nr_rrc_ue_decode_NR_BCCH_BCH_Message( module_id, gNB_index, (uint8_t*)pduP, pdu_len); + break; + default: + break; + } + + + return(0); + +} \ No newline at end of file diff --git a/openair2/RRC/NR_UE/defs.h b/openair2/RRC/NR_UE/defs.h deleted file mode 100644 index 37db3a9f02eb4f1ac622787614bac4bad821381d..0000000000000000000000000000000000000000 --- a/openair2/RRC/NR_UE/defs.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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 - */ - -/*! \file RRC/LITE/defs.h -* \brief RRC struct definitions and function prototypes -* \author Navid Nikaein and Raymond Knopp -* \date 2010 - 2014 -* \version 1.0 -* \company Eurecom -* \email: navid.nikaein@eurecom.fr, raymond.knopp@eurecom.fr -*/ - -#ifndef __OPENAIR_NR_RRC_DEFS_H__ -#define __OPENAIR_NR_RRC_DEFS_H__ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "collection/tree.h" -#include "rrc_types.h" -#include "PHY/defs.h" -#include "LAYER2/RLC/rlc.h" - -#include "COMMON/platform_constants.h" -#include "COMMON/platform_types.h" - -#include "LAYER2/MAC/defs.h" - -#include "SystemInformationBlockType1.h" -#include "SystemInformation.h" -#include "RRCConnectionReconfiguration.h" -#include "RRCConnectionReconfigurationComplete.h" -#include "RRCConnectionSetup.h" -#include "RRCConnectionSetupComplete.h" -#include "RRCConnectionRequest.h" -#include "RRCConnectionReestablishmentRequest.h" -#include "BCCH-DL-SCH-Message.h" -#include "BCCH-BCH-Message.h" -#if defined(Rel10) || defined(Rel14) -#include "MCCH-Message.h" -#include "MBSFNAreaConfiguration-r9.h" -#include "SCellToAddMod-r10.h" -#endif -#include "AS-Config.h" -#include "AS-Context.h" -#include "UE-EUTRA-Capability.h" -#include "MeasResults.h" - -/* for ImsiMobileIdentity_t */ -#include "MobileIdentity.h" - - -typedef struct NR_UE_RRC_INST_s { - nr_rrc_state_t rrc_state; - nr_rrc_sub_state_t rrc_sub_state; -#if 0 - OAI_UECapability_t *UECap; - uint8_t *UECapability; - uint8_t UECapability_size; - UE_RRC_INFO Info[NB_SIG_CNX_UE]; - SRB_INFO Srb0[NB_SIG_CNX_UE]; - SRB_INFO_TABLE_ENTRY Srb1[NB_CNX_UE]; - SRB_INFO_TABLE_ENTRY Srb2[NB_CNX_UE]; - HANDOVER_INFO_UE HandoverInfoUe; - uint8_t *SIB1[NB_CNX_UE]; - uint8_t sizeof_SIB1[NB_CNX_UE]; - uint8_t *SI[NB_CNX_UE]; - uint8_t sizeof_SI[NB_CNX_UE]; - uint8_t SIB1Status[NB_CNX_UE]; - uint8_t SIStatus[NB_CNX_UE]; - SystemInformationBlockType1_t *sib1[NB_CNX_UE]; - SystemInformation_t *si[NB_CNX_UE]; //!< Temporary storage for an SI message. Decoding happens in decode_SI(). - SystemInformationBlockType2_t *sib2[NB_CNX_UE]; - SystemInformationBlockType3_t *sib3[NB_CNX_UE]; - SystemInformationBlockType4_t *sib4[NB_CNX_UE]; - SystemInformationBlockType5_t *sib5[NB_CNX_UE]; - SystemInformationBlockType6_t *sib6[NB_CNX_UE]; - SystemInformationBlockType7_t *sib7[NB_CNX_UE]; - SystemInformationBlockType8_t *sib8[NB_CNX_UE]; - SystemInformationBlockType9_t *sib9[NB_CNX_UE]; - SystemInformationBlockType10_t *sib10[NB_CNX_UE]; - SystemInformationBlockType11_t *sib11[NB_CNX_UE]; - -#if defined(Rel10) || defined(Rel14) - uint8_t MBMS_flag; - uint8_t *MCCH_MESSAGE[NB_CNX_UE]; - uint8_t sizeof_MCCH_MESSAGE[NB_CNX_UE]; - uint8_t MCCH_MESSAGEStatus[NB_CNX_UE]; - MBSFNAreaConfiguration_r9_t *mcch_message[NB_CNX_UE]; - SystemInformationBlockType12_r9_t *sib12[NB_CNX_UE]; - SystemInformationBlockType13_r9_t *sib13[NB_CNX_UE]; -#endif -#ifdef CBA - uint8_t num_active_cba_groups; - uint16_t cba_rnti[NUM_MAX_CBA_GROUP]; -#endif - uint8_t num_srb; - struct SRB_ToAddMod *SRB1_config[NB_CNX_UE]; - struct SRB_ToAddMod *SRB2_config[NB_CNX_UE]; - struct DRB_ToAddMod *DRB_config[NB_CNX_UE][8]; - rb_id_t *defaultDRB; // remember the ID of the default DRB - MeasObjectToAddMod_t *MeasObj[NB_CNX_UE][MAX_MEAS_OBJ]; - struct ReportConfigToAddMod *ReportConfig[NB_CNX_UE][MAX_MEAS_CONFIG]; - struct QuantityConfig *QuantityConfig[NB_CNX_UE]; - struct MeasIdToAddMod *MeasId[NB_CNX_UE][MAX_MEAS_ID]; - MEAS_REPORT_LIST *measReportList[NB_CNX_UE][MAX_MEAS_ID]; - uint32_t measTimer[NB_CNX_UE][MAX_MEAS_ID][6]; // 6 neighboring cells - RSRP_Range_t s_measure; - struct MeasConfig__speedStatePars *speedStatePars; - struct PhysicalConfigDedicated *physicalConfigDedicated[NB_CNX_UE]; - struct SPS_Config *sps_Config[NB_CNX_UE]; - MAC_MainConfig_t *mac_MainConfig[NB_CNX_UE]; - MeasGapConfig_t *measGapConfig[NB_CNX_UE]; - double filter_coeff_rsrp; // [7] ??? - double filter_coeff_rsrq; // [7] ??? - float rsrp_db[7]; - float rsrq_db[7]; - float rsrp_db_filtered[7]; - float rsrq_db_filtered[7]; -#if defined(ENABLE_SECURITY) - /* KeNB as computed from parameters within USIM card */ - uint8_t kenb[32]; - uint8_t nh[32]; - int8_t nh_ncc; -#endif - - /* Used integrity/ciphering algorithms */ - CipheringAlgorithm_r12_t ciphering_algorithm; - e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm; -#endif - - MeasConfig_t *meas_config; - CellGroupConfig_t *cell_group_config; - RadioBearerConfig_t *radio_bearer_config; - -} NR_UE_RRC_INST_t; - -#include "proto.h" - -#endif -/** @} */ diff --git a/openair2/RRC/NR_UE/main_ue.c b/openair2/RRC/NR_UE/main_ue.c index 814e68717eaead22004f309b162fd8ae9a63fdd3..bbb3c0a64e237c618507b7b101d591f168744264 100644 --- a/openair2/RRC/NR_UE/main_ue.c +++ b/openair2/RRC/NR_UE/main_ue.c @@ -1,13 +1,7 @@ #include "defs.h" -#include "proto.h" -#include "extern.h" -#include "assertions.h" - - - - +#include "rrc_proto.h" int nr_l3_init_ue(void){ LOG_I(RRC, "[MAIN] NR UE MAC initialization...\n"); diff --git a/openair2/RRC/NR_UE/proto.h b/openair2/RRC/NR_UE/proto.h deleted file mode 100644 index 6e876297f6622785e2c650aa14cfd8eb9a8de772..0000000000000000000000000000000000000000 --- a/openair2/RRC/NR_UE/proto.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 - */ - -/*! \file proto.h - * \brief RRC functions prototypes for eNB and UE - * \author Navid Nikaein and Raymond Knopp - * \date 2010 - 2014 - * \email navid.nikaein@eurecom.fr - * \version 1.0 - - */ -/** \addtogroup _rrc - * @{ - */ - -#include "defs.h" - -// -// main_rrc.c -// -/**\brief Layer 3 initialization*/ -int nr_l3_init_ue(void); - -// -// UE_rrc.c -// - -/**\brief Initial the top level RRC structure instance*/ -uint8_t openair_rrc_top_init_ue_nr(void); - -/**\brief Decode DCCH from gNB, sent from lower layer through SRB3 - \param buffer encoded DCCH bytes stream message - \param size length of buffer*/ -int8_t nr_rrc_ue_decode_dcch(const uint8_t *buffer, const uint32_t size); - -/**\brief Decode RRC Connection Reconfiguration, sent from E-UTRA RRC Connection Reconfiguration v1510 carring EN-DC config - \param buffer encoded NR-RRC-Connection-Reconfiguration/Secondary-Cell-Group-Config message. - \param size length of buffer*/ -//TODO check to use which one -int8_t nr_rrc_ue_decode_rrcReconfiguration(const uint8_t *buffer, const uint32_t size); -int8_t nr_rrc_ue_decode_secondary_cellgroup_config(const uint8_t *buffer, const uint32_t size); - - -/**\brief Process NR RRC connection reconfiguration via SRB3 - \param rrcReconfiguration decoded rrc connection reconfiguration*/ -int8_t nr_rrc_ue_process_rrcReconfiguration(RRCReconfiguration_t *rrcReconfiguration); - -/**\prief Process measurement config from NR RRC connection reconfiguration message - \param meas_config measurement configuration*/ -int8_t nr_rrc_ue_process_meas_config(MeasConfig_t *meas_config); - -/**\prief Process secondary cell group config from NR RRC connection reconfiguration message or EN-DC primitives - \param cell_group_config secondary cell group configuration*/ -//TODO check EN-DC function call flow. -int8_t nr_rrc_ue_process_scg_config(CellGroupConfig_t *cell_group_config); - -/**\prief Process radio bearer config from NR RRC connection reconfiguration message - \param radio_bearer_config radio bearer configuration*/ -int8_t nr_rrc_ue_process_radio_bearer_config(RadioBearerConfig_t *radio_bearer_config); - -/** @}*/ diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 6e5bb3227c610bfada250d3e9ceae55f24182e2c..a7d420ebfe89ea98a7660499dd44e62faf2746a8 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -31,216 +31,159 @@ #define RRC_UE #define RRC_UE_C - -// header files for RRC message for NR might be change to add prefix in from of the file name. -#include "assertions.h" -#include "hashtable.h" -#include "asn1_conversions.h" -#include "defs.h" -#include "PHY/TOOLS/dB_routines.h" -#include "extern.h" -#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" -#include "LAYER2/RLC/rlc.h" -#include "COMMON/mac_rrc_primitives.h" -#include "UTIL/LOG/log.h" -#include "UTIL/LOG/vcd_signal_dumper.h" -#ifndef CELLULAR -#include "RRC/LITE/MESSAGES/asn1_msg.h" -#endif -#include "RRCConnectionRequest.h" -#include "RRCConnectionReconfiguration.h" -#include "UL-CCCH-Message.h" -#include "DL-CCCH-Message.h" -#include "UL-DCCH-Message.h" -#include "DL-DCCH-Message.h" -#include "BCCH-DL-SCH-Message.h" -#include "PCCH-Message.h" -#if defined(Rel10) || defined(Rel14) -#include "MCCH-Message.h" -#endif -#include "MeasConfig.h" -#include "MeasGapConfig.h" -#include "MeasObjectEUTRA.h" -#include "TDD-Config.h" -#include "UECapabilityEnquiry.h" -#include "UE-CapabilityRequest.h" -#include "RRC/NAS/nas_config.h" -#include "RRC/NAS/rb_config.h" -#if ENABLE_RAL -#include "rrc_UE_ral.h" -#endif - -#if defined(ENABLE_SECURITY) -# include "UTIL/OSA/osa_defs.h" -#endif - - -#if defined(ENABLE_ITTI) -#include "intertask_interface.h" -#endif - - - -// from NR SRB3 -uint8_t nr_rrc_ue_decode_dcch( - const uint8_t *buffer, - const uint32_t size -){ - // uper_decode by nr R15 rrc_connection_reconfiguration - - NR_RRC_DL_DCCH_Message_t *nr_dl_dcch_msg = (NR_RRC_DL_DCCH_Message_t *)0; - - uper_decode(NULL, - &asn_DEF_NR_RRC_DL_DCCH_Message, //might be added prefix later - (void**)&nr_dl_dcch_msg, - (uint8_t *)buffer, - size, 0, 0); - - if(nr_dl_dcch_msg != NULL){ - switch(nr_dl_dcch_msg->message.present){ - case DL_DCCH_MessageType_PR_c1: - - switch(nr_dl_dcch_msg->message.choice.c1.present){ - case DL_DCCH_MessageType__c1_PR_rrcReconfiguration: - nr_rrc_ue_process_rrcReconfiguration(&nr_dl_dcch_msg->message.choice.c1.choice.rrcReconfiguration); - break; - - case DL_DCCH_MessageType__c1_PR_NOTHING: - case DL_DCCH_MessageType__c1_PR_spare15: - case DL_DCCH_MessageType__c1_PR_spare14: - case DL_DCCH_MessageType__c1_PR_spare13: - case DL_DCCH_MessageType__c1_PR_spare12: - case DL_DCCH_MessageType__c1_PR_spare11: - case DL_DCCH_MessageType__c1_PR_spare10: - case DL_DCCH_MessageType__c1_PR_spare9: - case DL_DCCH_MessageType__c1_PR_spare8: - case DL_DCCH_MessageType__c1_PR_spare7: - case DL_DCCH_MessageType__c1_PR_spare6: - case DL_DCCH_MessageType__c1_PR_spare5: - case DL_DCCH_MessageType__c1_PR_spare4: - case DL_DCCH_MessageType__c1_PR_spare3: - case DL_DCCH_MessageType__c1_PR_spare2: - case DL_DCCH_MessageType__c1_PR_spare1: - default: - // not support or unuse - break; - } - break; - case DL_DCCH_MessageType_PR_NOTHING: - case DL_DCCH_MessageType_PR_messageClassExtension: - default: - // not support or unuse - break; - } - - // release memory allocation - free(nr_dl_dcch_msg); - }else{ - // log.. - } - - return 0; - -} +#include "rrc_list.h" +#include "rrc_defs.h" +#include "rrc_proto.h" +#include "rrc_vars.h" +#include "LAYER2/NR_MAC_UE/proto.h" // from LTE-RRC DL-DCCH RRCConnectionReconfiguration nr-secondary-cell-group-config (encoded) -uint8_t nr_rrc_ue_decode_secondary_cellgroup_config( +int8_t nr_rrc_ue_decode_secondary_cellgroup_config( const uint8_t *buffer, const uint32_t size ){ - CellGroupConfig_t *cellGroupConfig = (CellGroupConfig_t *)0; + NR_CellGroupConfig_t *cellGroupConfig = NULL; uper_decode(NULL, - &asn_DEF_CellGroupConfig, //might be added prefix later + &asn_DEF_NR_CellGroupConfig, //might be added prefix later (void **)&cellGroupConfig, (uint8_t *)buffer, size, 0, 0); - if(NR_UE_rrc_inst->cell_group_config == (CellGroupConfig_t *)0){ + if(NR_UE_rrc_inst->cell_group_config == NULL){ NR_UE_rrc_inst->cell_group_config = cellGroupConfig; nr_rrc_ue_process_scg_config(cellGroupConfig); }else{ nr_rrc_ue_process_scg_config(cellGroupConfig); - asn_DEF_CellGroupConfig.free_struct(asn_DEF_CellGroupConfig, cellGroupConfig, 0); + //asn_DEF_NR_CellGroupConfig.free_struct(asn_DEF_NR_CellGroupConfig, cellGroupConfig, 0); + SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)cellGroupConfig, 0); } - nr_rrc_mac_config_req_ue(); + //nr_rrc_mac_config_req_ue( module_id_t module_id, int CC_id, uint8_t gNB_index, NR_MIB_t *mibP, NR_MAC_CellGroupConfig_t *mac_cell_group_configP, NR_PhysicalCellGroupConfig_t *phy_cell_group_configP, NR_SpCellConfig_t *spcell_configP ); + + return 0; } // from LTE-RRC DL-DCCH RRCConnectionReconfiguration nr-secondary-cell-group-config (decoded) // RRCReconfiguration -uint8_t nr_rrc_ue_process_rrcReconfiguration(RRCReconfiguration_t *rrcReconfiguration){ +int8_t nr_rrc_ue_process_rrcReconfiguration(NR_RRCReconfiguration_t *rrcReconfiguration){ - switch(rrcReconfiguration.criticalExtensions.present){ - case RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration: - if(rrcReconfiguration.criticalExtensions.rrcReconfiguration->radioBearerConfig != (RadioBearerConfig_t *)0){ - if(NR_UE_rrc_inst->radio_bearer_config == (RadioBearerConfig_t *)0){ - NR_UE_rrc_inst->radio_bearer_config = rrcReconfiguration->radioBearerConfig; + switch(rrcReconfiguration->criticalExtensions.present){ + case NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration: + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.radioBearerConfig != NULL){ + if(NR_UE_rrc_inst->radio_bearer_config == NULL){ + NR_UE_rrc_inst->radio_bearer_config = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.radioBearerConfig; }else{ - nr_rrc_ue_process_radio_bearer_config(rrcReconfiguration->radioBearerConfig); + nr_rrc_ue_process_radio_bearer_config(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.radioBearerConfig); } } - if(rrcReconfiguration.criticalExtensions.rrcReconfiguration->secondaryCellGroup != (OCTET_STRING_t *)0){ - CellGroupConfig_t *cellGroupConfig = (CellGroupConfig_t *)0; + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.secondaryCellGroup != NULL){ + NR_CellGroupConfig_t *cellGroupConfig = NULL; uper_decode(NULL, - &asn_DEF_CellGroupConfig, //might be added prefix later + &asn_DEF_NR_CellGroupConfig, //might be added prefix later (void **)&cellGroupConfig, - (uint8_t *)rrcReconfiguration->secondaryCellGroup->buffer, - rrcReconfiguration->secondaryCellGroup.size, 0, 0); + (uint8_t *)rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.secondaryCellGroup->buf, + rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.secondaryCellGroup->size, 0, 0); - if(NR_UE_rrc_inst->cell_group_config == (CellGroupConfig_t *)0){ + if(NR_UE_rrc_inst->cell_group_config == NULL){ // first time receive the configuration, just use the memory allocated from uper_decoder. TODO this is not good implementation, need to maintain RRC_INST own structure every time. NR_UE_rrc_inst->cell_group_config = cellGroupConfig; nr_rrc_ue_process_scg_config(cellGroupConfig); }else{ // after first time, update it and free the memory after. nr_rrc_ue_process_scg_config(cellGroupConfig); - asn_DEF_CellGroupConfig.free_struct(asn_DEF_CellGroupConfig, cellGroupConfig, 0); + //asn_DEF_NR_CellGroupConfig.free_struct(asn_DEF_NR_CellGroupConfig, cellGroupConfig, 0); + SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)cellGroupConfig, 0); } } - if(rrcReconfiguration.criticalExtensions.rrcReconfiguration->measConfig != (MeasConfig *)0){ - if(NR_UE_rrc_inst->meas_config == (MeasConfig_t *)0){ - NR_UE_rrc_inst->meas_config = rrcReconfiguration->measConfig; + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.measConfig != NULL){ + if(NR_UE_rrc_inst->meas_config == NULL){ + NR_UE_rrc_inst->meas_config = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.measConfig; }else{ // if some element need to be updated - nr_rrc_ue_process_meas_config(rrcReconfiguration->measConfig); + nr_rrc_ue_process_meas_config(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.measConfig); } } - if(rrcReconfiguration.criticalExtensions.rrcReconfiguration->lateNonCriticalExtension != (OCTET_STRING_t *)0){ + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.lateNonCriticalExtension != NULL){ // unuse now } - if(rrcReconfiguration.criticalExtensions.rrcReconfiguration->nonCriticalExtension != (RRCReconfiguration_IEs__nonCriticalExtension *)0){ + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration.nonCriticalExtension != NULL){ // unuse now } break; - case RRCReconfiguration__criticalExtensions_PR_NOTHING: - case RRCReconfiguration__criticalExtensions_PR_criticalExtensionsFuture: + case NR_RRCReconfiguration__criticalExtensions_PR_NOTHING: + case NR_RRCReconfiguration__criticalExtensions_PR_criticalExtensionsFuture: default: break; } - nr_rrc_mac_config_req_ue(); + //nr_rrc_mac_config_req_ue(); + + return 0; } -uint8_t nr_rrc_ue_process_meas_config(MeasConfig_t *meas_config){ +int8_t nr_rrc_ue_process_meas_config(NR_MeasConfig_t *meas_config){ + return 0; } -uint8_t nr_rrc_ue_process_scg_config(CellGroupConfig_t *cell_group_config){ +int8_t nr_rrc_ue_process_scg_config(NR_CellGroupConfig_t *cell_group_config){ + int i; + if(NR_UE_rrc_inst->cell_group_config==NULL){ + // initial list + + if(cell_group_config->spCellConfig != NULL){ + if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ + if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList != NULL){ + for(i=0; i<cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; ++i){ + RRC_LIST_MOD_ADD(NR_UE_rrc_inst->BWP_Downlink_list, cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i], bwp_Id); + } + } + } + } + + + }else{ + // maintain list + if(cell_group_config->spCellConfig != NULL){ + if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ + // process element of list to be add by RRC message + if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList != NULL){ + for(i=0; i<cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; ++i){ + RRC_LIST_MOD_ADD(NR_UE_rrc_inst->BWP_Downlink_list, cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i], bwp_Id); + } + } + + + // process element of list to be release by RRC message + if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList != NULL){ + for(i=0; i<cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList->list.count; ++i){ + NR_BWP_Downlink_t *freeP = NULL; + RRC_LIST_MOD_REL(NR_UE_rrc_inst->BWP_Downlink_list, bwp_Id, *cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList->list.array[i], freeP); + if(freeP != NULL){ + SEQUENCE_free(&asn_DEF_NR_BWP_Downlink, (void *)freeP, 0); + } + } + } + } + } + } + return 0; } -uint8_t nr_rrc_ue_process_radio_bearer_config(RadioBearerConfig_t *radio_bearer_config){ +int8_t nr_rrc_ue_process_radio_bearer_config(NR_RadioBearerConfig_t *radio_bearer_config){ + return 0; } -uint8_t openair_rrc_top_init_ue_nr(void){ +int8_t openair_rrc_top_init_ue_nr(void){ if(NB_NR_UE_INST > 0){ NR_UE_rrc_inst = (NR_UE_RRC_INST_t *)malloc(NB_NR_UE_INST * sizeof(NR_UE_RRC_INST_t)); @@ -248,29 +191,206 @@ uint8_t openair_rrc_top_init_ue_nr(void){ // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. - + // init RRC lists + RRC_LIST_INIT(NR_UE_rrc_inst->RLC_Bearer_Config_list, NR_maxLC_ID); + RRC_LIST_INIT(NR_UE_rrc_inst->SchedulingRequest_list, NR_maxNrofSR_ConfigPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst->TAG_list, NR_maxNrofTAGs); + RRC_LIST_INIT(NR_UE_rrc_inst->TDD_UL_DL_SlotConfig_list, NR_maxNrofSlots); + RRC_LIST_INIT(NR_UE_rrc_inst->BWP_Downlink_list, NR_maxNrofBWPs); + RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[0], 3); // for init-dl-bwp + RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[1], 3); // for dl-bwp id=0 + RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[2], 3); // for dl-bwp id=1 + RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[3], 3); // for dl-bwp id=2 + RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[4], 3); // for dl-bwp id=3 + RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[0], 10); + RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[1], 10); + RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[2], 10); + RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[3], 10); + RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[4], 10); + RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[0], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[1], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[2], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[3], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[4], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[0], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[1], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[2], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[3], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[4], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[0], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[1], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[2], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[3], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[4], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[0], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[1], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[2], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[3], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[4], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[0], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[1], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[2], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[3], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[4], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[0], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[1], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[2], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[3], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[4], NR_maxNrofZP_CSI_RS_Sets); + RRC_LIST_INIT(NR_UE_rrc_inst->NZP_CSI_RS_Resource_list, NR_maxNrofNZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst->NZP_CSI_RS_ResourceSet_list, NR_maxNrofNZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst->CSI_IM_Resource_list, NR_maxNrofCSI_IM_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst->CSI_IM_ResourceSet_list, NR_maxNrofCSI_IM_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst->CSI_SSB_ResourceSet_list, NR_maxNrofCSI_SSB_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst->CSI_ResourceConfig_list, NR_maxNrofCSI_ResourceConfigurations); + RRC_LIST_INIT(NR_UE_rrc_inst->CSI_ReportConfig_list, NR_maxNrofCSI_ReportConfigurations); }else{ - NR_UE_rrc_inst = (NR_UE_RRC_INST_t *)0; + NR_UE_rrc_inst = NULL; } + + return 0; } -uint8_t nr_ue_process_rlc_bearer_list(CellGroupConfig_t *cell_group_config){ +int8_t nr_ue_process_rlc_bearer_list(NR_CellGroupConfig_t *cell_group_config){ + return 0; }; -uint8_t nr_ue_process_secondary_cell_list(CellGroupConfig_t *cell_group_config){ +int8_t nr_ue_process_secondary_cell_list(NR_CellGroupConfig_t *cell_group_config){ + return 0; }; -uint8_t nr_ue_process_mac_cell_group_config(MAC_CellGroupConfig_t *mac_cell_group_config){ +int8_t nr_ue_process_mac_cell_group_config(NR_MAC_CellGroupConfig_t *mac_cell_group_config){ + return 0; }; -uint8_t nr_ue_process_physical_cell_group_config(PhysicalCellGroupConfig_t *phy_cell_group_config){ +int8_t nr_ue_process_physical_cell_group_config(NR_PhysicalCellGroupConfig_t *phy_cell_group_config){ + return 0; }; -uint8_t nr_ue_process_spcell_config(SpCellConfig_t *spcell_config){ +int8_t nr_ue_process_spcell_config(NR_SpCellConfig_t *spcell_config){ + return 0; }; + +/*brief decode BCCH-BCH (MIB) message*/ +int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message( + const module_id_t module_id, + const uint8_t gNB_index, + uint8_t *const bufferP, + const uint8_t buffer_len){ + int i; + NR_BCCH_BCH_Message_t *bcch_message = NULL; + NR_MIB_t *mib = NR_UE_rrc_inst->mib; + + asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + &asn_DEF_NR_BCCH_BCH_Message, + (void **)&bcch_message, + (const void *)bufferP, + buffer_len ); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E( RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", + module_id, + dec_rval.consumed ); + + for (i=0; i<buffer_len; i++) + printf("%02x ",bufferP[i]); + + printf("\n"); + // free the memory + SEQUENCE_free( &asn_DEF_NR_BCCH_BCH_Message, (void *)bcch_message, 1 ); + return -1; + } + + // copy into rrc instance + memcpy( (void *)mib, + (void *)&bcch_message->message.choice.mib, + sizeof(NR_MIB_t) ); + + nr_rrc_mac_config_req_ue( 0, 0, 0, mib, NULL, NULL, NULL); + + return 0; +} + + +// from NR SRB3 +int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message( + const module_id_t module_id, + const uint8_t gNB_index, + const uint8_t *bufferP, + const uint32_t buffer_len){ + // uper_decode by nr R15 rrc_connection_reconfiguration + int32_t i; + NR_DL_DCCH_Message_t *nr_dl_dcch_msg = NULL; + + asn_dec_rval_t dec_rval = uper_decode( NULL, + &asn_DEF_NR_DL_DCCH_Message, + (void**)&nr_dl_dcch_msg, + (uint8_t *)bufferP, + buffer_len, 0, 0); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E( RRC, "[UE %"PRIu8"] Failed to decode NR_DL_DCCH_Message (%zu bits)\n", + module_id, + dec_rval.consumed ); + + for (i=0; i<buffer_len; i++) + printf("%02x ",bufferP[i]); + + printf("\n"); + // free the memory + SEQUENCE_free( &asn_DEF_NR_DL_DCCH_Message, (void *)nr_dl_dcch_msg, 1 ); + return -1; + } + + if(nr_dl_dcch_msg != NULL){ + switch(nr_dl_dcch_msg->message.present){ + case NR_DL_DCCH_MessageType_PR_c1: + + switch(nr_dl_dcch_msg->message.choice.c1.present){ + case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: + nr_rrc_ue_process_rrcReconfiguration(&nr_dl_dcch_msg->message.choice.c1.choice.rrcReconfiguration); + break; + + case NR_DL_DCCH_MessageType__c1_PR_NOTHING: + case NR_DL_DCCH_MessageType__c1_PR_spare15: + case NR_DL_DCCH_MessageType__c1_PR_spare14: + case NR_DL_DCCH_MessageType__c1_PR_spare13: + case NR_DL_DCCH_MessageType__c1_PR_spare12: + case NR_DL_DCCH_MessageType__c1_PR_spare11: + case NR_DL_DCCH_MessageType__c1_PR_spare10: + case NR_DL_DCCH_MessageType__c1_PR_spare9: + case NR_DL_DCCH_MessageType__c1_PR_spare8: + case NR_DL_DCCH_MessageType__c1_PR_spare7: + case NR_DL_DCCH_MessageType__c1_PR_spare6: + case NR_DL_DCCH_MessageType__c1_PR_spare5: + case NR_DL_DCCH_MessageType__c1_PR_spare4: + case NR_DL_DCCH_MessageType__c1_PR_spare3: + case NR_DL_DCCH_MessageType__c1_PR_spare2: + case NR_DL_DCCH_MessageType__c1_PR_spare1: + default: + // not support or unuse + break; + } + break; + case NR_DL_DCCH_MessageType_PR_NOTHING: + case NR_DL_DCCH_MessageType_PR_messageClassExtension: + default: + // not support or unuse + break; + } + + // release memory allocation + SEQUENCE_free( &asn_DEF_NR_DL_DCCH_Message, (void *)nr_dl_dcch_msg, 1 ); + }else{ + // log.. + } + + return 0; + +} diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..b999d88fe9edc37ef5805485ed4b9b2ae8366023 --- /dev/null +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -0,0 +1,116 @@ +/* + * 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 + */ + +/*! \file RRC/LITE/defs.h +* \brief RRC struct definitions and function prototypes +* \author Navid Nikaein and Raymond Knopp +* \date 2010 - 2014 +* \version 1.0 +* \company Eurecom +* \email: navid.nikaein@eurecom.fr, raymond.knopp@eurecom.fr +*/ + +#ifndef __OPENAIR_NR_RRC_DEFS_H__ +#define __OPENAIR_NR_RRC_DEFS_H__ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "platform_types.h" + +#include "LAYER2/NR_MAC_UE/mac.h" +#include "rrc_list.h" +#include "NR_asn_constant.h" +#include "NR_MeasConfig.h" +#include "NR_CellGroupConfig.h" +#include "NR_RadioBearerConfig.h" +#include "NR_RLC-Bearer-Config.h" +#include "asn1_constants.h" +#include "NR_SchedulingRequestToAddMod.h" +#include "NR_MIB.h" +#include "NR_BCCH-BCH-Message.h" +#include "NR_DL-DCCH-Message.h" + +#define NB_NR_UE_INST 1 + +typedef uint32_t channel_t; + +typedef struct NR_UE_RRC_INST_s { + + NR_MeasConfig_t *meas_config; + NR_CellGroupConfig_t *cell_group_config; + NR_RadioBearerConfig_t *radio_bearer_config; + + NR_MIB_t *mib; + + // lists + // CellGroupConfig.rlc-BearerToAddModList + RRC_LIST_TYPE(NR_RLC_Bearer_Config_t, NR_maxLC_ID) RLC_Bearer_Config_list; + // CellGroupConfig.mac-CellGroupConfig.schedulingrequest + RRC_LIST_TYPE(NR_SchedulingRequestToAddMod_t, NR_maxNrofSR_ConfigPerCellGroup) SchedulingRequest_list; + // CellGroupConfig.mac-CellGroupConfig.TAG + RRC_LIST_TYPE(NR_TAG_ToAddMod_t, NR_maxNrofTAGs) TAG_list; + // CellGroupConfig.spCellConfig.spCellConfigDedicated.tdduldlslotconfig + RRC_LIST_TYPE(NR_TDD_UL_DL_SlotConfig_t, NR_maxNrofSlots) TDD_UL_DL_SlotConfig_list; + + // CellGroupConfig.spCellConfig.spCellConfigDedicated.bwps + RRC_LIST_TYPE(NR_BWP_Downlink_t, NR_maxNrofBWPs) BWP_Downlink_list; + //BWP-DownlinkDedicated 0=INIT-DL-BWP, 1..4 for DL-BWPs + // CellGroupConfig.spCellConfig.spCellConfigDedicated.initialdlbwp.pdcchconfig.controlresourceset + RRC_LIST_TYPE(NR_ControlResourceSet_t, 3) ControlResourceSet_list[5]; + // CellGroupConfig.spCellConfig.spCellConfigDedicated.initialdlbwp.pdcchconfig.searchspace + RRC_LIST_TYPE(NR_SearchSpace_t, 10) SearchSpace_list[5]; + // CellGroupConfig.spCellConfig.spCellConfigDedicated.initialdlbwp.pdcchconfig.slotformatindicator + RRC_LIST_TYPE(NR_SlotFormatCombinationsPerCell_t, NR_maxNrofAggregatedCellsPerCellGroup) SlotFormatCombinationsPerCell_list[5]; + // CellGroupConfig.spCellConfig.spCellConfigDedicated.initialdlbwp.pdschconfig + RRC_LIST_TYPE(NR_TCI_State_t, NR_maxNrofTCI_States) TCI_State_list[5]; + // CellGroupConfig.spCellConfig.spCellConfigDedicated.initialdlbwp.pdschconfig + RRC_LIST_TYPE(NR_RateMatchPattern_t, NR_maxNrofRateMatchPatterns) RateMatchPattern_list[5]; + // CellGroupConfig.spCellConfig.spCellConfigDedicated.initialdlbwp.pdschconfig + RRC_LIST_TYPE(NR_ZP_CSI_RS_Resource_t, NR_maxNrofZP_CSI_RS_Resources) ZP_CSI_RS_Resource_list[5]; + // CellGroupConfig.spCellConfig.spCellConfigDedicated.initialdlbwp.pdschconfig + RRC_LIST_TYPE(NR_ZP_CSI_RS_ResourceSet_t, NR_maxNrofZP_CSI_RS_Sets) Aperidic_ZP_CSI_RS_ResourceSet_list[5]; + // CellGroupConfig.spCellConfig.spCellConfigDedicated.initialdlbwp.pdschconfig + RRC_LIST_TYPE(NR_ZP_CSI_RS_ResourceSet_t, NR_maxNrofZP_CSI_RS_Sets) SP_ZP_CSI_RS_ResourceSet_list[5]; + + // TODO check the way to implement mutiple list inside bwps + // uplink bwp also + + // CellGroupConfig.spCellConfig.spCellConfigDedicated + RRC_LIST_TYPE(NR_NZP_CSI_RS_Resource_t, NR_maxNrofNZP_CSI_RS_Resources) NZP_CSI_RS_Resource_list; + // CellGroupConfig.spCellConfig.spCellConfigDedicated + RRC_LIST_TYPE(NR_NZP_CSI_RS_ResourceSet_t, NR_maxNrofNZP_CSI_RS_ResourceSets) NZP_CSI_RS_ResourceSet_list; + // CellGroupConfig.spCellConfig.spCellConfigDedicated + RRC_LIST_TYPE(NR_CSI_IM_Resource_t, NR_maxNrofCSI_IM_Resources) CSI_IM_Resource_list; + // CellGroupConfig.spCellConfig.spCellConfigDedicated + RRC_LIST_TYPE(NR_CSI_IM_ResourceSet_t, NR_maxNrofCSI_IM_ResourceSets) CSI_IM_ResourceSet_list; + // CellGroupConfig.spCellConfig.spCellConfigDedicated + RRC_LIST_TYPE(NR_CSI_SSB_ResourceSet_t, NR_maxNrofCSI_SSB_ResourceSets) CSI_SSB_ResourceSet_list; + // CellGroupConfig.spCellConfig.spCellConfigDedicated + RRC_LIST_TYPE(NR_CSI_ResourceConfig_t, NR_maxNrofCSI_ResourceConfigurations) CSI_ResourceConfig_list; + // CellGroupConfig.spCellConfig.spCellConfigDedicated + RRC_LIST_TYPE(NR_CSI_ReportConfig_t, NR_maxNrofCSI_ReportConfigurations) CSI_ReportConfig_list; + +} NR_UE_RRC_INST_t; + +#endif +/** @} */ diff --git a/openair2/RRC/NR_UE/rrc_list.h b/openair2/RRC/NR_UE/rrc_list.h new file mode 100644 index 0000000000000000000000000000000000000000..5bad103dd43160e3281134d1c25c6cb2533f6d31 --- /dev/null +++ b/openair2/RRC/NR_UE/rrc_list.h @@ -0,0 +1,82 @@ +#ifndef _RRC_LIST_H_ +#define _RRC_LIST_H_ + + +#define RRC_LIST_TYPE(T, N) \ + struct { \ + T *entries[N]; \ + int next[N]; \ + int prev[N]; \ + int start; \ + int count; \ + } + +// initial function for the certain list, storage number of entry, initial pointer and corresponding links +#define RRC_LIST_INIT(list, c) \ + do { \ + int iterator; \ + (list).count = (c); \ + for(iterator=0; iterator<c; ++iterator){ \ + (list).entries[iterator] = NULL; \ + (list).next[iterator] = -1; \ + (list).prev[iterator] = -1; \ + (list).start = -1; \ + } \ + }while(0) + + +// check the entry by id first then update or create new entry. +#define RRC_LIST_MOD_ADD(list, new, id_name) \ + do { \ + int iterator; \ + for(iterator=(list).start; iterator!=-1; iterator=(list).next[iterator]){ \ + if((new)->id_name == (list).entries[iterator]->id_name){ \ + (list).entries[iterator] = (new); \ + break; \ + } \ + } \ + if(iterator==-1){ \ + for(iterator=0; iterator<(list).count; ++iterator){ \ + if((list).entries[iterator] == NULL){ \ + (list).next[iterator] = (list).start; \ + (list).prev[iterator] = -1; \ + if((list).start != -1){ \ + (list).prev[list.start] = iterator; \ + } \ + (list).start = iterator; \ + (list).entries[iterator] = (new); \ + break; \ + } \ + } \ + } \ + }while(0) + +// search entries by id, unlink from the list and output free pointer for upper function to release memory +#define RRC_LIST_MOD_REL(list, id_name, id, free) \ + do{ \ + int iterator; \ + for(iterator=(list).start; iterator!=-1; iterator=(list).next[iterator]){ \ + if(id == (list).entries[iterator]->id_name){ \ + if((list).prev[iterator] == -1){ \ + (list).start = (list).next[iterator]; \ + }else{ \ + (list).next[(list).prev[iterator]] = (list).next[iterator]; \ + } \ + if((list).next[iterator] != -1){ \ + (list).prev[(list).next[iterator]] = (list).prev[iterator]; \ + } \ + (free) = (list).entries[iterator]; \ + (list).entries[iterator] = NULL; \ + break; \ + } \ + } \ + }while(0) + + +#define RRC_LIST_FOREACH(list, i) \ + for((i)=(list).start; (i) != -1; (i)=(list).next[i]) + +#define RRC_LIST_ENTRY(list, i) \ + list.entries[i] + +#endif \ No newline at end of file diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h new file mode 100644 index 0000000000000000000000000000000000000000..e3ff9b0d3d77ae50ae810ab6953f2260728d97c3 --- /dev/null +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -0,0 +1,107 @@ +/* + * 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 + */ + +/*! \file proto.h + * \brief RRC functions prototypes for eNB and UE + * \author Navid Nikaein and Raymond Knopp + * \date 2010 - 2014 + * \email navid.nikaein@eurecom.fr + * \version 1.0 + + */ +/** \addtogroup _rrc + * @{ + */ +#ifndef _RRC_PROTO_H_ +#define _RRC_PROTO_H_ + + +#include "rrc_defs.h" +#include "NR_RRCReconfiguration.h" +#include "NR_MeasConfig.h" +#include "NR_CellGroupConfig.h" +#include "NR_RadioBearerConfig.h" +// +// main_rrc.c +// +/**\brief Layer 3 initialization*/ +int nr_l3_init_ue(void); + +// +// UE_rrc.c +// + +/**\brief Initial the top level RRC structure instance*/ +int8_t openair_rrc_top_init_ue_nr(void); + + + +/**\brief Decode RRC Connection Reconfiguration, sent from E-UTRA RRC Connection Reconfiguration v1510 carring EN-DC config + \param buffer encoded NR-RRC-Connection-Reconfiguration/Secondary-Cell-Group-Config message. + \param size length of buffer*/ +//TODO check to use which one +int8_t nr_rrc_ue_decode_rrcReconfiguration(const uint8_t *buffer, const uint32_t size); +int8_t nr_rrc_ue_decode_secondary_cellgroup_config(const uint8_t *buffer, const uint32_t size); + + +/**\brief Process NR RRC connection reconfiguration via SRB3 + \param rrcReconfiguration decoded rrc connection reconfiguration*/ +int8_t nr_rrc_ue_process_rrcReconfiguration(NR_RRCReconfiguration_t *rrcReconfiguration); + +/**\prief Process measurement config from NR RRC connection reconfiguration message + \param meas_config measurement configuration*/ +int8_t nr_rrc_ue_process_meas_config(NR_MeasConfig_t *meas_config); + +/**\prief Process secondary cell group config from NR RRC connection reconfiguration message or EN-DC primitives + \param cell_group_config secondary cell group configuration*/ +//TODO check EN-DC function call flow. +int8_t nr_rrc_ue_process_scg_config(NR_CellGroupConfig_t *cell_group_config); + +/**\prief Process radio bearer config from NR RRC connection reconfiguration message + \param radio_bearer_config radio bearer configuration*/ +int8_t nr_rrc_ue_process_radio_bearer_config(NR_RadioBearerConfig_t *radio_bearer_config); + +/**\brief decode NR BCCH-BCH (MIB) message + \param module_idP module id + \param gNB_index gNB index + \param sduP pointer to buffer of ASN message BCCH-BCH + \param sdu_len length of buffer*/ +int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message(const module_id_t module_id, const uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len); + +/**\brief Decode NR DCCH from gNB, sent from lower layer through SRB3 + \param module_id module id + \param gNB_index gNB index + \param buffer encoded DCCH bytes stream message + \param size length of buffer*/ +int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message(const module_id_t module_id, const uint8_t gNB_index, const uint8_t *buffer, const uint32_t size); + +/**\brief interface between MAC and RRC thru SRB0 (RLC TM/no PDCP) + \param module_id module id + \param CC_id component carrier id + \param gNB_index gNB index + \param frameP pointer to frame for calculation + \param channel indicator for channel of the pdu + \param pduP pointer to pdu + \param pdu_len data length of pdu*/ +int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const uint32_t *frameP, const channel_t channel, const uint8_t* pduP, const sdu_size_t pdu_len); + +/** @}*/ +#endif \ No newline at end of file diff --git a/openair2/RRC/NR_UE/rrc_types.h b/openair2/RRC/NR_UE/rrc_types.h deleted file mode 100644 index b5540145b098234bccd42667a78c352e8d6e4ab7..0000000000000000000000000000000000000000 --- a/openair2/RRC/NR_UE/rrc_types.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 - */ - -/*! \file rrc_types.h -* \brief rrc types and subtypes -* \author Navid Nikaein and Raymond Knopp -* \date 2011 - 2014 -* \version 1.0 -* \company Eurecom -* \email: navid.nikaein@eurecom.fr, raymond.knopp@eurecom.fr -*/ - -#ifndef NR_RRC_TYPES_H_ -#define NR_RRC_TYPES_H_ - -typedef enum nr_rrc_state_e { - //RRC_STATE_INACTIVE=0, - //RRC_STATE_IDLE, - //RRC_STATE_CONNECTED, - - //RRC_STATE_FIRST = RRC_STATE_INACTIVE, - //RRC_STATE_LAST = RRC_STATE_CONNECTED, - RRC_STATE_IDLE = 0, - RRC_STATE_INACTIVE, - RRC_STATE_CONNECTED, - - RRC_STATE_FIRST = RRC_STATE_IDLE, - RRC_STATE_LAST = RRC_STATE_CONNECTED - -} nr_rrc_state_t; - -typedef enum nr_rrc_sub_state_e { - //RRC_SUB_STATE_INACTIVE=0, - - //RRC_SUB_STATE_IDLE_SEARCHING, - //RRC_SUB_STATE_IDLE_RECEIVING_SIB, - //RRC_SUB_STATE_IDLE_SIB_COMPLETE, - //RRC_SUB_STATE_IDLE_CONNECTING, - //RRC_SUB_STATE_IDLE, - - //RRC_SUB_STATE_CONNECTED, - - //RRC_SUB_STATE_INACTIVE_FIRST = RRC_SUB_STATE_INACTIVE, - //RRC_SUB_STATE_INACTIVE_LAST = RRC_SUB_STATE_INACTIVE, - - //RRC_SUB_STATE_IDLE_FIRST = RRC_SUB_STATE_IDLE_SEARCHING, - //RRC_SUB_STATE_IDLE_LAST = RRC_SUB_STATE_IDLE, - - //RRC_SUB_STATE_CONNECTED_FIRST = RRC_SUB_STATE_CONNECTED, - //RRC_SUB_STATE_CONNECTED_LAST = RRC_SUB_STATE_CONNECTED, -} nr_rrc_sub_state_t; - -#endif /* RRC_TYPES_H_ */ diff --git a/openair2/RRC/NR_UE/vars.h b/openair2/RRC/NR_UE/rrc_vars.h similarity index 92% rename from openair2/RRC/NR_UE/vars.h rename to openair2/RRC/NR_UE/rrc_vars.h index f21b49e9164be36344043ff658c3430a65626daa..8df7d7174bb6c454b97f71a1019de12c5e09df69 100644 --- a/openair2/RRC/NR_UE/vars.h +++ b/openair2/RRC/NR_UE/rrc_vars.h @@ -32,10 +32,8 @@ #ifndef __OPENAIR_NR_RRC_VARS_H__ #define __OPENAIR_NR_RRC_VARS_H__ -#include "defs.h" -#include "LAYER2/RLC/rlc.h" -#include "COMMON/mac_rrc_primitives.h" -#include "LAYER2/MAC/defs.h" +#include "rrc_defs.h" NR_UE_RRC_INST_t *NR_UE_rrc_inst; + #endif diff --git a/openair2/UTIL/OMG/defs.h b/openair2/UTIL/OMG/defs.h index 96700e6e9ce380ed07245df0a2914aba79c0da47..06c9bf6e73fe1a5adc3c2f6022157969ccfd43ce 100644 --- a/openair2/UTIL/OMG/defs.h +++ b/openair2/UTIL/OMG/defs.h @@ -36,6 +36,7 @@ //typedef char bool; #include <stdbool.h> +#include "omg_constants.h" #ifdef STANDALONE typedef struct { diff --git a/targets/RT/USER/nr-softmodem.h b/targets/RT/USER/nr-softmodem.h index 5a85e6deaf6809f796fdefb8a4901221c8afd243..13ac6dc329ff43dd786fc09ab9a423f61b2578af 100644 --- a/targets/RT/USER/nr-softmodem.h +++ b/targets/RT/USER/nr-softmodem.h @@ -30,6 +30,7 @@ #include "PHY/types.h" #include "flexran_agent.h" +#include "PHY/defs_gNB.h" #if defined(ENABLE_ITTI) #if defined(ENABLE_USE_MME) diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c index ac0acef776eab4587da32c72ab81a8d5a6408197..49a2307c9e8a1fd8f5d79ec5f6ecbd3ade8c7035 100644 --- a/targets/RT/USER/nr-ue.c +++ b/targets/RT/USER/nr-ue.c @@ -61,6 +61,8 @@ #include "T.h" extern double cpuf; +static nfapi_config_request_t config_t; +static nfapi_config_request_t* config =&config_t; #define FRAME_PERIOD 100000000ULL #define DAQ_PERIOD 66667ULL @@ -413,7 +415,7 @@ static void *UE_thread_synch(void *arg) { //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); //UE->rfdevice.trx_stop_func(&UE->rfdevice); // sleep(1); - nr_init_frame_parms_ue(&UE->frame_parms); + nr_init_frame_parms_ue(config,&UE->frame_parms); /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { LOG_E(HW,"Could not start the device\n"); oai_exit=1; diff --git a/tmp/ci-scripts/Jenkinsfile-gitlab b/tmp/ci-scripts/Jenkinsfile-gitlab new file mode 100644 index 0000000000000000000000000000000000000000..64572e7cb3ba09673652918558a75868bbc5ef70 --- /dev/null +++ b/tmp/ci-scripts/Jenkinsfile-gitlab @@ -0,0 +1,143 @@ +// Comments + +pipeline { + agent { + label 'bellatrix' + } + options { + disableConcurrentBuilds() + timestamps() + gitLabConnection('OAI GitLab') + gitlabBuilds(builds: ["Build eNb-USRP", "Build basic-sim", "Build phy-sim", "Analysis with cppcheck"]) + } + + stages { + stage ("Verify Guidelines") { + steps { + echo "Git URL is ${GIT_URL}" + echo "GitLab Act is ${env.gitlabActionType}" + script { + if ("MERGE".equals(env.gitlabActionType)) { + // GitLab-Jenkins plugin integration is lacking to perform the merge by itself + // Doing it manually --> it may have merge conflicts + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" + sh "zip -r -qq localZip.zip ." + + // Running astyle options on the list of modified files by the merge request + // For the moment, there is no fail criteria. Just a notification of number of files that do not follow + sh "./ci-scripts/checkCodingFormattingRules.sh --src-branch ${env.gitlabSourceBranch} --target-branch ${env.gitlabTargetBranch}" + def res=readFile('./oai_rules_result.txt').trim(); + if ("0".equals(res)) { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): All Changed files in Merge Request follow OAI Formatting Rules" + addGitLabMRComment comment: message + } else { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Some Changed files in Merge Request DO NOT follow OAI Formatting Rules" + addGitLabMRComment comment: message + } + } else { + echo "Git Branch is ${GIT_BRANCH}" + echo "Git Commit is ${GIT_COMMIT}" + + sh "zip -r -qq localZip.zip ." + // Running astyle options on all C/H files in the repository + // For the moment, there is no fail criteria. Just a notification of number of files that do not follow + sh "./ci-scripts/checkCodingFormattingRules.sh" + } + } + } + } + + stage ("Variant Builds") { + parallel { + stage ("Analysis with cppcheck") { + steps { + gitlabCommitStatus(name: "Analysis with cppcheck") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + stage ("Build eNb-USRP") { + steps { + gitlabCommitStatus(name: "Build eNb-USRP") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + stage ("Build basic simulator") { + steps { + gitlabCommitStatus(name: "Build basic-sim") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant basic-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + stage ("Build physical simulators") { + steps { + gitlabCommitStatus(name: "Build phy-sim") { + sh "./ci-scripts/buildOnVM.sh --workspace $WORKSPACE --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } + } + } + post { + always { + script { + dir ('archives') { + sh "zip -r vm_build_logs.zip basic_sim enb_usrp phy_sim cppcheck" + } + if(fileExists('archives/vm_build_logs.zip')) { + archiveArtifacts artifacts: 'archives/vm_build_logs.zip' + } + if ("MERGE".equals(env.gitlabActionType)) { + sh "./ci-scripts/reportBuildLocally.sh --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger merge-request --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" + } else { + sh "./ci-scripts/reportBuildLocally.sh --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger push --branch ${GIT_BRANCH} --commit ${GIT_COMMIT}" + } + if(fileExists('build_results.html')) { + archiveArtifacts artifacts: 'build_results.html' + } + } + } + } + } + + stage ("Destroy all Virtual Machines") { + steps { + sh "./ci-scripts/destroyAllRunningVM.sh --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + } + post { + always { + script { + // Stage destroy may not be run if error in previous stage + sh "./ci-scripts/destroyAllRunningVM.sh --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } + } + success { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + def message2 = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ") -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")" + slackSend channel: 'ci-enb', color: 'good', message: message2 + } else { + slackSend channel: 'ci-enb', color: 'good', message: message + } + } + } + failure { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + def message2 = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ") -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")" + slackSend channel: 'ci-enb', color: 'danger', message: message2 + } else { + slackSend channel: 'ci-enb', color: 'danger', message: message + } + } + } + } +}